Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Header File Cross #include

Tags:

c++

header

Say, I have two classes: A && B ; One Header file myheader.h :

....
class A{
public:
    void display(B* c);
};
class B{
public:
    void display(A* c);
};
.....

Compiler gave me error: 'B' has not been declared( in A::display )As expected.

So I wrote two separated headers for A and B: aheader.h(including definition of class A) and bheader.h(including class B);

In aheader.h:

#include "bheader.h"

In bheader.h:

#include "aheader.h"

so far, so good .

But the problem occurs when I start to write the implementation.cpp:

#include "aheader.h"
#include "bheader.h"
void A::display(B* c){}
void B::display(A* c){}

Now,A' has not been declared.(in B::display)

Don't know how to describe this problem in brief.

I'm using Ubuntu14,Eclipse CDT,Linux GCC & Gnu Makd Builder.

I'm new to C++,I guess this problem occurs when linking. And I really hope someone to give me an explanation or a solution. Thank you !

like image 737
gone Avatar asked Nov 29 '22 11:11

gone


2 Answers

Instead of mutually including the header files in each other, use forward declarations. In aheader.h:

class B;

class A{
public:
    void display(B* c);
};

And in bheader.h:

class A;

class B{
public:
    void display(A* c);
};
like image 29
jlahd Avatar answered Dec 02 '22 01:12

jlahd


This is quite common when beginning with C / C++

The usual aproach in C++ is to have all the unrelated classes separated, each one in its own header file. Always (I mean it, ALWAYS) the header file MUST be protected against recursive inclusion. This is done by appending an IFDEF at the beginning of the header file, so the file is included only once:

I. e. file aheader.h:

#ifndef __AHEADER_H__
#define __AHEADER_H__

//All the header code comes here...

#endif

So when including the header file, the compiler will do the following:

  1. Is __AHEADER_H__ defined?
  2. It is not yet defined, so it compiles the header.
  3. The compiler defines __AHEADER_H__ now.
  4. If at any other point the file is included again:
  5. Is __AHEADER_H__ defined?
  6. Yes, don't compile again the header.

Ok, this is one part of your problem. But lets go to your actual problem.

You are having the error because, as the compiler tells you, the other class is not defined. In other words, the compiler does not know what A (or B) is. You cannot include "aheader.h" in "bheader.h", since this will throw the "B is not defined" error:

  1. bheader will include aheader
  2. aheader begins to be processed
  3. class A is found, which contains a method with a B parameter.
  4. What is B?
  5. Error here!

Of course, if you include them the other way (bheader.h included in aheader.h) the error would be "A is not defined", just with the same explanation.

The solution?

Just forward define the class:

In bheader.h:

#ifndef __BHEADER_H__
#define __BHEADER_H__

class A; //Forward definition. We don't have any member definition, just we are telling 
         //the compiler "Trust me, this is a class"

class B{
public:
   void display(A* c);
}
#endif

The same would have to be done in aheader.h.

And finally, in order to be able to use A or B in your implementation code, you should include the actual header file of the class.

file implementation.cpp:

#include "aheader.h"
#include "bheader.h"
void A::display(B* c){}
//And so on...

Forward declaration can be used whenever you don't need to have the complete class definition (i.e.):

  • When a class is used only as the parameters or as the result of a funciton.
  • When a class is used only with a pointer.

You cannot have forward declaration when you need to have the complete class definition (i.e.):

  • When used as a class member.
  • When inheriting from it.

By the way, the usual way of separating classes would be also to separate the implementation into one .cpp file per class, having at the end:

  • aheader.h
  • aheader.cpp
  • bheader.h
  • bheader.cpp
like image 52
LoPiTaL Avatar answered Dec 02 '22 00:12

LoPiTaL