Simple VC++6 Header Question

Slick_mick_00
Slick_mick_00 used Ask the Experts™
on
I have a question about header files. I used app wizard to create a dialog application, then created my own classes, 3 which were interacting with each other but I'm now having problems with the header files. The compiler complains that either classes haven't been defined or an error about nesting.
Could you please tell me where I should put the #include statements. If you need the code let me know. Thanks
Michael
Slick_mick_00@hotmail.com
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
As a general guideline you should avoid #include's in header files. If you are referencing a class B in the declaration of class A you can try to use forward declarations, if you only use pointers and references to class B.

//////// header file A.h
class B;  // forward declaraion
class A {
public:
    void Init( const B& b );  // no need to know the actual implementation of B
    B* m_pb;  // same as above
    B& convert();  // same as above
    //B b;  // if you need something like this, you have to #include "B.h"
};

Apart from that, #include's should appear at the top of the file. For further information it would be helpful to have the essential parts of your source code, i.e. those that force inclusion of header files.

.f

Author

Commented:
The problem seems to be that I ahve 3 separate .h 's and three .cpp files. Is it possible to include files with these postings?

Commented:
Look for circular dependencies, e.g. A.h including B.h, which in turn includes A.h. You would need to resolve this issue, most likley through the use of forward declarations. I cannot give you a detailed answer though, without knowing the details of your problem at hand.

.f
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
Are forward declarations the same as function prototypes?

Commented:
Sometimes. Take a look at this example:

void do_something();

int main() {
    do_something();
    return( 0 );
}

void do_something() {
}

In this case the prototype of do_something is also a forward declaration. However, there are forward declarations that are just that and do not contain any additional information:

class A;  // forward declaration without being a prototype
class B {
    A* m_pa;
};

Hope this helped to clearify things.

.f

Commented:
Hello. Please verify that you inluded your files (*.h and *.cpp) into project. You can do this in workspace window by switching to FileView tab. Also if you have circular dependencies you must write something like this :

---- class1.h -------
/* Lines below are very important. They will help to avoid of including .h file more than once. */
#ifndef CLASS1_H
#define CLASS1_H

#include "class2.h"
#include "class3.h"

class Class1 {
   ...
   Your class  definition
   ...
};

#endif //ifndef CLASS1_H

---- class2.h -------
/* Lines below are very important. They will help to avoid of including .h file more than once. */

#ifndef CLASS2_H
#define CLASS2_H

#include "class1.h"
#include "class3.h"

class Class2 {
   ...
   Your class  definition
   ...
};

#endif //ifndef CLASS2_H


---- class3.h -------
/* Lines below are very important. They will help to avoid of including .h file more than once. */

#ifndef CLASS3_H
#define CLASS3_H

#include "class1.h"
#include "class2.h"

class Class3 {
   ...
   Your class  definition
   ...
};

#endif //ifndef CLASS3_H


-------------

I hope that this will help you.
Regards,
zubok32

Commented:
Erm, nope. Apart from the ugly and rather compile time expensive practice of including headers in header files, it won't compile, if any of the classes actually needs one of the other class implementations. This example shows pretty drastically what is meant by "circular dependency". What it states is something like: "i don't know how my code works -- let's just make it safe and include everything everywhere". Sorry if this sounds harsh, but bad practices shouldn't be taugth to someone just starting out.

.f

Author

Commented:
They are included in the project under the FileView Tab.
The classes do require the other class implementations. Is there somehwere I can send or post my source code? An e-mail address?
Michael

Commented:
I don't think it's a good idea to answer this question 'offline' by exchanging information through email. This site is meant to provide information, not email addresses. Someone else who comes across this question and decides to buy the answer may be a bit disappointed to find that the answer is an email address.

Back to the topic itself. First of all, if you find that two classes mutually depend on each other, it's likely to be the result of a design error. If you cannot solve this, you will have to break the circular chain of inclusion somewhere. Let me illustrate this with two classes A and B that depend on each other.

// file A.h
#include "B.h"
class A {
public:
    B m_B;
};

// file B.h
#include "A.h"
class B {
public:
    A m_A;
};

This will not compile, since A depends on B which in turn depends on A depending on B, .... Let's break the inclusion chain by removing the reference to class B from A.h:

// file A.h
// instead of including B.h let's provide a forward declaration
class B;
class A {
public:
    A::A();
    A::~A();
    B* m_pB;
};

// file A.cpp
// make sure, B* is defined throughout the lifetime of A
#include "B.h"
A::A() {
    m_pB = new B;
}
A::~A() {
    delete m_pB;
}
// instead of writing m_B.some_member() you will have to write m_pB->some_member() instead

// file B.h --  remains unchanged
#include "A.h"
class B {
public:
    A m_A;
};

I hope you can translate to your specific problem. Without your source code I cannot be more specific to your problem.

.f

Author

Commented:
// Ant.cpp: implementation of the CAnt class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Ants2.h"
#include "Ant.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAnt::CAnt()
{

}

CAnt::~CAnt()
{

}

void CAnt::ThreadHandle()
{

}

void CAnt::CDrawing_DrawAnt(CPoint point,BOOL DelAnt)
{

}
// AntController.cpp: implementation of the CAntController class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Ants2.h"
#include "AntController.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
UINT AntThreadBridge(LPVOID);

CAntController::CAntController()
{

}

CAntController::~CAntController()
{

}

void CAntController::MakeNewRandomAnt()
{

      CPoint point;
point.x=0;
point.y=0;

CAnt* pAnt = new CAnt;

pAnt->m_att_Aggression = 50;

pAnt->m_pt_position = point;
pAnt->m_pt_velocity = point;

pAnt->m_state_health =100;
pAnt->m_state_hungar =100;

pAnt->pAntController= this;
pAnt->pDrawing = pDrawing;

AfxBeginThread(AntThreadBridge,pAnt);


}



// Ants2.cpp : Defines the class behaviors for the application.
//
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "stdafx.h"
#include "Ants2.h"
#include "Ants2Dlg.h"


/////////////////////////////////////////////////////////////////////////////
// CAnts2App

BEGIN_MESSAGE_MAP(CAnts2App, CWinApp)
      //{{AFX_MSG_MAP(CAnts2App)
            // NOTE - the ClassWizard will add and remove mapping macros here.
            //    DO NOT EDIT what you see in these blocks of generated code!
      //}}AFX_MSG
      ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAnts2App construction

CAnts2App::CAnts2App()
{
      // TODO: add construction code here,
      // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CAnts2App object

CAnts2App theApp;

/////////////////////////////////////////////////////////////////////////////
// CAnts2App initialization

BOOL CAnts2App::InitInstance()
{
      // Standard initialization
      // If you are not using these features and wish to reduce the size
      //  of your final executable, you should remove from the following
      //  the specific initialization routines you do not need.

#ifdef _AFXDLL
      Enable3dControls();                  // Call this when using MFC in a shared DLL
#else
      Enable3dControlsStatic();      // Call this when linking to MFC statically
#endif

      CAnts2Dlg dlg;
      m_pMainWnd = &dlg;
      int nResponse = dlg.DoModal();
      if (nResponse == IDOK)
      {
            // TODO: Place code here to handle when the dialog is
            //  dismissed with OK
      }
      else if (nResponse == IDCANCEL)
      {
            // TODO: Place code here to handle when the dialog is
            //  dismissed with Cancel
      }

      // Since the dialog has been closed, return FALSE so that we exit the
      //  application, rather than start the application's message pump.
      return FALSE;
}
// Ants2Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "Ants2.h"
#include "Ants2Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "Ant.h"
#include "Drawing.h"
#include "AntController.h"


UINT AntThreadBridge(LPVOID params)
{
CAnt* pInfo = (CAnt*) params;
pInfo->ThreadHandle();
return(0);
}

/////////////////////////////////////////////////////////////////////////////
// CAnts2Dlg dialog

CAnts2Dlg::CAnts2Dlg(CWnd* pParent /*=NULL*/)
      : CDialog(CAnts2Dlg::IDD, pParent)
{


      //{{AFX_DATA_INIT(CAnts2Dlg)
            // NOTE: the ClassWizard will add member initialization here
      //}}AFX_DATA_INIT
      // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
      m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

      //Pointers
       pAntController = new CAntController;
       pDrawing = new CDrawing;

       //Flags
       flagProgramStarted = FALSE;

}

void CAnts2Dlg::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CAnts2Dlg)
            // NOTE: the ClassWizard will add DDX and DDV calls here
      //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAnts2Dlg, CDialog)
      //{{AFX_MSG_MAP(CAnts2Dlg)
      ON_WM_PAINT()
      ON_WM_QUERYDRAGICON()
      ON_WM_KEYDOWN()
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAnts2Dlg message handlers

BOOL CAnts2Dlg::OnInitDialog()
{
      CDialog::OnInitDialog();

      // Set the icon for this dialog.  The framework does this automatically
      //  when the application's main window is not a dialog
      SetIcon(m_hIcon, TRUE);                  // Set big icon
      SetIcon(m_hIcon, FALSE);            // Set small icon
      
      // TODO: Add extra initialization here
      
      return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CAnts2Dlg::OnPaint()
{
      if (IsIconic())
      {
            CPaintDC dc(this); // device context for painting

            SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

            // Center icon in client rectangle
            int cxIcon = GetSystemMetrics(SM_CXICON);
            int cyIcon = GetSystemMetrics(SM_CYICON);
            CRect rect;
            GetClientRect(&rect);
            int x = (rect.Width() - cxIcon + 1) / 2;
            int y = (rect.Height() - cyIcon + 1) / 2;

            // Draw the icon
            dc.DrawIcon(x, y, m_hIcon);
      }
      else
      {
            CDialog::OnPaint();
      }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CAnts2Dlg::OnQueryDragIcon()
{
      return (HCURSOR) m_hIcon;
}

void CAnts2Dlg::BeginProgram()
{

      ::Beep(10000,1000);
      Setup_pDrawing();
Setup_pAntController();

pAntController->MakeNewRandomAnt();



}

void CAnts2Dlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
      if(nChar == 49 && !flagProgramStarted)
      {
            BeginProgram();
            flagProgramStarted = TRUE;
      }


      CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CAnts2Dlg::Setup_pDrawing()
{
      CRect rect;
      GetClientRect(&rect);
      pDrawing->m_rect = rect;
}

void CAnts2Dlg::Setup_pAntController()
{
pAntController->pDrawing = pDrawing;
}
// Drawing.cpp: implementation of the CDrawing class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Ants2.h"
#include "Drawing.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDrawing::CDrawing()
{

}

CDrawing::~CDrawing()
{

}

void CDrawing::SetupCoordinates(CDC* pDC)
{
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(1000,1000);
pDC->SetViewportExt(m_rect.Width(),m_rect.Height());
pDC->SetViewportOrg(m_rect.Width()/2,m_rect.Height()/2);
}


/*
void CDrawing::MoveAnt(CPoint, CPoint, CAnt *)
{

}
*/


// Ant.h: interface for the CAnt class.
//
//////////////////////////////////////////////////////////////////////



#if !defined(AFX_ANT_H__EC8EF78B_AA08_42ED_A984_FE3F9D5BCD39__INCLUDED_)
#define AFX_ANT_H__EC8EF78B_AA08_42ED_A984_FE3F9D5BCD39__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Drawing.h"
#include "AntController.h"

class CAnt  
{
public:
      void CDrawing_DrawAnt(CPoint point,BOOL DelAnt);
      CAntController* pAntController;

      CDrawing* pDrawing;
//Constructor & Destructor
      CAnt();
      virtual ~CAnt();

//Functions      
      void ThreadHandle();
      
// Ants Attributes
      double m_att_Aggression;

//Ants State
      double m_state_health;
      double m_state_hungar;

      CPoint m_pt_position;
      CPoint m_pt_velocity;
};

#endif // !defined(AFX_ANT_H__EC8EF78B_AA08_42ED_A984_FE3F9D5BCD39__INCLUDED_)


// AntController.h: interface for the CAntController class.
//
//////////////////////////////////////////////////////////////////////


#if !defined(AFX_ANTCONTROLLER_H__53C43F85_B520_46A5_80C3_C78DECB388EC__INCLUDED_)
#define AFX_ANTCONTROLLER_H__53C43F85_B520_46A5_80C3_C78DECB388EC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include "Ant.h"
#include "Drawing.h"






class CAntController  
{
public:
      CDrawing* pDrawing;
      void MakeNewRandomAnt();
      CAntController();
      virtual ~CAntController();

};

#endif // !defined(AFX_ANTCONTROLLER_H__53C43F85_B520_46A5_80C3_C78DECB388EC__INCLUDED_)



// Ants2.h : main header file for the ANTS2 application
//





#if !defined(AFX_ANTS2_H__C1A8CFCC_2EF7_439A_B5DD_A395D91F434B__INCLUDED_)
#define AFX_ANTS2_H__C1A8CFCC_2EF7_439A_B5DD_A395D91F434B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
      #error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h"            // main symbols



/////////////////////////////////////////////////////////////////////////////
// CAnts2App:
// See Ants2.cpp for the implementation of this class
//

class CAnts2App : public CWinApp
{
public:
      CAnts2App();

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CAnts2App)
      public:
      virtual BOOL InitInstance();
      //}}AFX_VIRTUAL

// Implementation

      //{{AFX_MSG(CAnts2App)
            // NOTE - the ClassWizard will add and remove member functions here.
            //    DO NOT EDIT what you see in these blocks of generated code !
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};


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

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_ANTS2_H__C1A8CFCC_2EF7_439A_B5DD_A395D91F434B__INCLUDED_)


// Ants2Dlg.h : header file
//

#if !defined(AFX_ANTS2DLG_H__623794AF_615A_4EFC_BE0D_6B06143FB7D6__INCLUDED_)
#define AFX_ANTS2DLG_H__623794AF_615A_4EFC_BE0D_6B06143FB7D6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000



#include "Ant.h"
#include "Drawing.h"
#include "AntController.h"





/////////////////////////////////////////////////////////////////////////////
// CAnts2Dlg dialog

class CAnts2Dlg : public CDialog
{
// Construction
public:
      void Setup_pAntController();
      void Setup_pDrawing();
      BOOL flagProgramStarted;
      void BeginProgram();
      CAntController* pAntController;
      CDrawing* pDrawing;
      CAnts2Dlg(CWnd* pParent = NULL);      // standard constructor
      
// Dialog Data
      //{{AFX_DATA(CAnts2Dlg)
      enum { IDD = IDD_ANTS2_DIALOG };
            // NOTE: the ClassWizard will add data members here
      //}}AFX_DATA

      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CAnts2Dlg)
      protected:
      virtual void DoDataExchange(CDataExchange* pDX);      // DDX/DDV support
      //}}AFX_VIRTUAL

// Implementation
protected:
      HICON m_hIcon;

      // Generated message map functions
      //{{AFX_MSG(CAnts2Dlg)
      virtual BOOL OnInitDialog();
      afx_msg void OnPaint();
      afx_msg HCURSOR OnQueryDragIcon();
      afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_ANTS2DLG_H__623794AF_615A_4EFC_BE0D_6B06143FB7D6__INCLUDED_)



// Drawing.h: interface for the CDrawing class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DRAWING_H__CDB29FE5_C1E5_4082_A391_D6F486A32A51__INCLUDED_)
#define AFX_DRAWING_H__CDB29FE5_C1E5_4082_A391_D6F486A32A51__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Ant.h"


class CDrawing  
{
public:
      CRect m_rect;
      void SetupCoordinates(CDC*);
      CDrawing();
      virtual ~CDrawing();

      //Ant Drawing
      //void MoveAnt(CPoint start,CPoint finish,CAnt* pAnt);

};

#endif // !defined(AFX_DRAWING_H__CDB29FE5_C1E5_4082_A391_D6F486A32A51__INCLUDED_)



Its the only I could do it!!
Michael

Commented:
* Ant.h: replace the following two lines

#include "Drawing.h"
#include "AntController.h"

by

class CDrawing;
class CAntController;

and move those 2 #include's to Ant.cpp


* AntController.h: replace the following lines

#include "Ant.h"
#include "Drawing.h"

by

class CDrawing;

and #include "Ant.h" in AntController.cpp


* Ants2Dlg.h: replace the following lines

#include "Ant.h"
#include "Drawing.h"
#include "AntController.h"

by

class CDrawing;
class CAntController;

and move the appropriate #include's to the Ants2Dlg.cpp file


* Drawing.h: replace the following line

#include "Ant.h"

by

class CAnt;

and move the #include to Ant.cpp.


Those 'class Cxxx;' are called forward declarations. Since you are only using pointers to the classes in your class declarations all the compiler needs to know is, if there is a class with the specified name. Once it has compiled to assembly code there is no difference between any pointers anymore, so the compiler only needs to check during compilation whether the pointer will point to a valid object. Possibly you will have to write 'extern class Cxxx;' if the above steps do not solve your problem. Hope this helps you.

.f

Author

Commented:
Ok thats Great. I got thing to compile and run sucessfully. However I can't access the member function when I add the following code:

void CAnt::ThreadHandle()
{

while(1)
{
     ::Sleep(1000);
     pDrawing->DrawAnt(m_pt_position_prev,TRUE);
     m_pt_position_prev = m_pt_position;
     ...
     ...
     ...
}



--------------------Configuration: Ants2 - Win32 Debug--------------------
Compiling...
Ant.cpp
C:\Program Files\Microsoft Visual Studio\MyProjects\Ants2\Ant.cpp(37) : error C2027: use of undefined type 'CDrawing'
        c:\program files\microsoft visual studio\myprojects\ants2\ant.h(14) : see declaration of 'CDrawing'
C:\Program Files\Microsoft Visual Studio\MyProjects\Ants2\Ant.cpp(37) : error C2227: left of '->DrawAnt' must point to class/struct/union
AntController.cpp
Ants2Dlg.cpp
Generating Code...
Error executing cl.exe.

Ants2.exe - 2 error(s), 0 warning(s)



This I don't understand as I have:
class CDrawing;
in the Ants.h file.

Regards
Michael
Commented:
Like I said, "move those 2 #include's to Ant.cpp", i.e. put

#include "Drawing.h"

before you using the class for the first time. As I've stated, the type of a class doesn't need to be know when you only use pointers. In your actual implementation you need to know the class though, i.e. you need to #include the definition.

.f

Author

Commented:
Thanks very much. Its all sorted now.
Regards
Michael
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
Recommendation: Accept comment from fl0yd

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

DominicCronin
EE Cleanup Volunteer

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial