Fethi Dilmi
Fethi Dilmi

Reputation: 161

Namespaces with multiple cyclic inclusion

I've 3 classes that belong to a namespace "MyNS". "A" uses the "B" and "C", while both "B" and "C" use "A". Here are the structure of my headers:

//mynamespace.h
#ifndef SOMENAMESPACE_H
#define SOMENAMESPACE_H
namespace MyNS {
     class A;
     class B;
     class C;
}
#endif
/*******************************************************/
//A.h
#ifndef A_H
#define A_H

#include "mynamespace.h"
#include "B.h"
#include "C.h"

class MyNS::A {
    ..
    MyNS::B someMethod(args);
    MyNS::C someMethod2(args);
    ..
};
#endif
/*******************************************************/
//B.h
#ifndef B_H
#define B_H

#include "mynamespace.h"
#include "A.h"

class MyNS::B {
    ..
    MyNS::A *someMember;
    ..
};
#endif
/*******************************************************/
//C.h
#ifndef C_H
#define C_H

#include "mynamespace.h"
#include "A.h"

class MyNS::C {
    ..
    MyNS::A *someMember;
    ..
};
#endif

Each of the classes has a C++ source file that includes the line:

using namespace MyNS;

The compiler is stopped by the B.h header guards, that's why I get an "incomplete type 'class B'" error in A::someMethod(args).

I know I could have included all the class definitions inside "mynamespace.h", but the classes are long which made my header file bloated, that's why I had to separate them like this.

How can I make this code work with separate header files ?

Upvotes: 1

Views: 256

Answers (1)

Benjy Kessler
Benjy Kessler

Reputation: 7636

The correct way to do this is using forward declaration. Do not include A.h in C.h and B.h. Only actually perform #include "A.h" in B.cpp and C.cpp. The forward declaration in the namespace should be enough.

//mynamespace.h
#ifndef SOMENAMESPACE_H
#define SOMENAMESPACE_H
namespace MyNS {
     class A;
     class B;
     class C;
}
#endif
/*******************************************************/
//A.h
#ifndef A_H
#define A_H

#include "mynamespace.h"
#include "B.h"
#include "C.h"

class MyNS::A {
    ..
    MyNS::B someMethod(args);
    MyNS::C someMethod2(args);
    ..
};
#endif
/*******************************************************/
//B.h
#ifndef B_H
#define B_H

#include "mynamespace.h"

class MyNS::B {
    ..
    MyNS::A *someMember;
    ..
};
#endif
/*******************************************************/
//C.h
#ifndef C_H
#define C_H

#include "mynamespace.h"

class MyNS::C {
    ..
    MyNS::A *someMember;
    ..
};
#endif

Upvotes: 2

Related Questions