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.
openujsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.