1

I'm wondering why the code bellow is not working. In b.cpp, class B uses class A, but it fails because the declaration of the class A is not found. However, a.hpp is included just before. Why the #include "a.hpp" is not working here?

Thanks for any help!

//===============================================
//file: a.hpp
//===============================================
#ifndef _A_HPP
#define _A_HPP

#include "b.hpp"

class A{
    public:
        A();
        // others methods using B here
};

#endif


//===============================================
//file: a.cpp
//===============================================
#include "a.hpp"

A::A(){}


//===============================================
//file: b.hpp
//===============================================
#ifndef _B_HPP
#define _B_HPP

#include "a.hpp"

class B{
    public:
        B(A a);
};

#endif
//===============================================
//file: b.cpp
//===============================================
#include "b.hpp"

B::B(A a){}



SHELL$ g++ -c a.cpp
In file included from a.hpp:7,
                 from a.cpp:4:
b.hpp:11: error: expected ‘)’ before ‘a’
Dan Fego
  • 13,644
  • 6
  • 48
  • 59
user744629
  • 1,961
  • 1
  • 18
  • 27

6 Answers6

2

You need to use Forward declarations to break such circular dependency.
However, note that once you forward declare a type, that type becomes an Incomplete Type for the compiler and there are restrictions on how you can use the Incomplete type

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

This won't work. In you header files you should only include references or pointers to the other class. Then you can forward declare A or B, e.g.:

//===============================================
//file: b.hpp
//===============================================
#ifndef _B_HPP
#define _B_HPP

class A;

class B{
    public:
        B(A& a);
};

#endif
KenE
  • 1,805
  • 10
  • 6
0

Remove the

#include "b.hpp"

from a.h and only have a forward declaration - assuming you use pointers to B in A:

//A.hpp

class B; //forward declaration

class A{
    public:
        A();
        // others methods using B here
};

Also: Macro names starting with underscore _ are reserved by the standard and should not be used. Replace _B_HPP with simply B_HPP.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

Why do you need a cyclic #include like that? If you just need for the compiler to know a class exists (so it can be a parameter et cetera), just forward declare it like this:

class A;

Don't cyclically include files. Even with the guards, they'll both only be included once, sure, but then you're still going to run into a mention of A before the compiler gets to its definition, or a mention of B before the compiler gets to its definition.

  • I was thinking an #include was better, to not duplicate code and make maintenace easy. But ok, the duplicated code is just "class A;" and it should not be much longer in a real long source code... – user744629 Jan 25 '12 at 20:53
0

When b.hpp includes a.hpp, _A_HPP is already defined, so the precompiler ignore the content of the file, so in the line B(A a), the compiler doesn't know about A.

if you really need these includes, try move the #include "b.hpp" to the end of a.hpp (or declare class A; in the head of b.hpp).

asaelr
  • 5,438
  • 1
  • 16
  • 22
0

In A.hpp, do not include B.hpp or inline A implementations that call B methods.

Use class B; in A.hpp (a forward declaration) if you need to refer to B& or B*.

Instead, put those A implementations that call B methods in A.cpp and include B.hpp in A.cpp.

kfmfe04
  • 14,936
  • 14
  • 74
  • 140