user744629
user744629

Reputation: 2041

headers include and cyclic dependency

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’

Upvotes: 1

Views: 295

Answers (6)

KenE
KenE

Reputation: 1805

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

Upvotes: 1

kfmfe04
kfmfe04

Reputation: 15327

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.

Upvotes: 0

asaelr
asaelr

Reputation: 5456

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).

Upvotes: 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.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258568

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.

Upvotes: 0

Alok Save
Alok Save

Reputation: 206518

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

Upvotes: 2

Related Questions