• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 336
  • Last Modified:

C++ Weird behavior: Compile error (C2027)

I am getting error
error C2027: use of undefined type 'Phil' at line:

int leftStatus = p->pPhil->getStatusForLeftNeighbor(p->m_ID);
pPhil of type is member for Thread class. Why would it complain about that line? Both Phil and Thread class are defined in same file. So there is no need for include or extern.


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define MAX_PHIL 5
#define DEBUG 1
#define TIMEFRAME 200

enum { STATE_THINKING = 100, STATE_EATING };


//Global Event handel
static HANDLE gEvent;

///////////////////////////////////////////////////////////////////////////////
class Phil;
class Thread
{

public:
      Thread()
      {
            leftChop = rightChop = -1;

            HANDLE hnd = CreateThread(NULL,0,ThreadProc,this,0,&m_ThreadID);
            if(hnd == NULL)
            {
            }

            m_State = STATE_THINKING;
            pPhil = 0;
      }
      ~Thread();

      static DWORD WINAPI ThreadProc(LPVOID lpParameter)
      {
            Thread*p = (Thread*)lpParameter;
            if(p == 0) return 0;

            p->m_ID++;
#if DEBUG
            
            printf("Thread %d is running. Status= %s.\n", p->m_ThreadID, p->getStatus(p->m_State));
#endif


            char buf[40];
            time_t oldtime, newtime= 0;
            struct tm  *ts;
            oldtime = time(0);

            ts = localtime(&oldtime);
            strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
              printf("Starting time = %d, %s\n\n", &oldtime, buf);
                  

            for(;;)  
            {
                  time_t ntime = time(0);

                  int leftStatus = p->pPhil->getStatusForLeftNeighbor(p->m_ID);
                  int rightStatus =  p->pPhil->getStatusForRightNeighbor(p->m_ID);

                  if(leftStatus == STATE_THINKING
                        && rightStatus == STATE_THINKING )
                  {
                        p->m_State = STATE_EATING;
            #if DEBUG
                        printf("%d thread ID (%d) is EATING.\n", p->m_ThreadID, p->m_ID);
            #endif
                  }

                  if( WaitForSingleObject(gEvent,5000) == WAIT_OBJECT_0)break;
            }
            
            printf("Thread %d is exiting.\n", p->m_ThreadID);

            //return 0;      
      };

      static DWORD m_ID;
      DWORD m_ThreadID;
      int m_State;
      Phil* pPhil;
      

      int leftChop, rightChop;

      void assignChops(int threadID, int id, int size)
      {
            if( id < size ) rightChop = id+1;
            else rightChop = 0;

            if( id > 0 ) leftChop = id-1;
            else leftChop = size;

            if( id == 0 ) leftChop = size - 1;
            if( id == size - 1) rightChop = 0;

            printf("%d thread ID (%d) is assigned left chop = %d and right chop = %d.\n", threadID, id, leftChop, rightChop);
      };

      char* getStatus(int state)
      {
            char* s;
            switch(state)
            {
                  case(STATE_THINKING):
                        s = "STATE_THINKING";
                        break;
                  case(STATE_EATING):
                        s = "STATE_EATING";
                        break;
            }
            return s;
      }
};

class Phil
{
public:
      Phil()
      {
            gEvent = CreateEvent(NULL,true,false,NULL);
      }

      void process(void)
      {
            char buf[40];
            time_t oldtime, newtime= 0;
            struct tm  *ts;
            oldtime = time(0);

            ts = localtime(&oldtime);
            strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
              printf("Starting time = %d, %s\n\n", &oldtime, buf);
                  

            for(;;)  
            {
                  time_t ntime = time(0);

                  if(ntime > oldtime + TIMEFRAME)
                  {
                        SetEvent(gEvent);
                        break;
                  }

                  if(ntime > newtime)
                  {
                        newtime = ntime;
                        ts = localtime(&ntime);
                        strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
                          printf("Current time = %d, %s\n", newtime, buf);
                  }
            }
            
      }
      
      void initiate()
      {
            for(int i =0;i<MAX_PHIL; i++)
            {
                  m_pThreadArray[i] = new Thread();
                  m_pThreadArray[i]->pPhil = (Phil*)this;
                  m_pThreadArray[i]->assignChops(m_pThreadArray[i]->m_ThreadID, m_pThreadArray[i]->m_ID, MAX_PHIL);
            }
      }

      void clean()
      {
            for(int i =0;i<MAX_PHIL; i++)
            {
                  delete m_pThreadArray[i];
            }
      }
      DWORD getStatusForLeftNeighbor(int id)
      {
            if(id == 0)
                  return m_pThreadArray[MAX_PHIL-1]->m_State;
            else
                  return m_pThreadArray[id-1]->m_State;

      };
      
      DWORD getStatusForRightNeighbor(int id)
      {
            if(id == MAX_PHIL-1)
                  return m_pThreadArray[0]->m_State;
            else
                  return m_pThreadArray[id+1]->m_State;
      };

      Thread* m_pThreadArray[MAX_PHIL];
};



DWORD Thread::m_ID = 0;

//////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
      Phil Aphil;
      Aphil.initiate();
      Aphil.process();

          return 1;
}


/////////////////////////////////////////////
by the way where is zone C++. C++ should have its own zone.
0
openujs
Asked:
openujs
  • 2
1 Solution
 
evilrixSenior Software Engineer (Avast)Commented:
you use Phil in your thread class yet you've only provided a forward definition first. Move the definition of Phil class before thread class.
0
 
openujsAuthor Commented:
evilrix,

Well if you do that, then I get - error C2027: use of undefined type 'Thread'. It is more like Chicken and egg problem.
0
 
Infinity08Commented:
You'll have to move all the member function definitions out of the class definition - preferably in their own .cpp file.
//// instead of :

class Foo {
  public :
    void bar() {
      // implementation here
    }
};


//// do this :

/* -- foo.h -- */

#ifndef FOO_H
#define FOO_H

class Foo {
  public :
    void bar();
};

#endif /* FOO_H */


/* -- foo.cpp -- */

#include "foo.h"

void Foo::bar() {
  // implementation here
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>>  then I get - error C2027
Sorry, I missed that -- I was reading the Q from my phone, so it was hard to read the code >:|

>> It is more like Chicken and egg problem.
Cyclically dependant functions are a sign of bad design. It's never a good idea to have co-dependencies between classes.

As Infinity08 said, you can; however, still get this to build by having both the class definitions before the implementation of the functions. The best way to structure this is to each class defintion in its own header file and separate the functions for each class in their own separate .cpp files. In each header you can forward declare the other class, so in phil.h forward declare thread and in thread.h forward declare phil. In each .cpp file include both headers.

The following link explains this in more detail: http://www.eventhelix.com/realtimemantra/HeaderFileIncludePatterns.htm
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now