Code looks like this:
class B {/*something*/};
class D1: public B {
public:
void set() = 0;
friend int D2::get(D1&);
private:
int a;
}
class D2: public B {
public:
int get(D1& d) {return d.a;}
}
I’ve included "B.h" in both derived class’ .h files("D1.h" and "D2.h") and also “D2.h” in D1, "D1.h" in D2…but keep getting compiling error:
...\D2.h ... use of undefined type D1
So what I’m doing wrong? Thanks.
You created a circular inclusion: you included
D1.hintoD2.hand you also includedD2.hintoD1.h. Circular inclusion never works and never achieves anything.Your circular inclusion is a direct consequence of circular dependency between your class definitions. In your code both class definitions refer to each other in a way that requires both class types to be complete (to be completely defined). This means that your code, as is, cannot be compiled, regardless of what you do. You need to break the circular dependency between class definitions.
In your case it can be done in the following way.
Keep
D1.hunchanged, i.e. keep includingD2.hintoD1.hand keep the definition of classD1as is.However, do not include
D1.hintoD2.hInstead introduce a forward declaration ofD1intoD2.hChange the definition of
D2toNote: do not attempt to define method
getright in the definition of classD2. You have to relocate the definition ofD2::getto some other place, where the full definition ofD1is also visible (like inD2.cppfor example, which should include bothD1.handD2.h)That’s it. A side-effect of defining
D2::getthis way is that it becomes non-inline. If you really want to keep it inline, you’ll have to define it asand also make sure it is somehow included only after the full definition of
D1. You can place it, for example, into a third header file (D2_aux.hor something like that) and remember to include it after theD1.h.Of course, a better way to try to solve this issue is to rethink the entire design. Do you really need that friend declaration inside
D1? Maybe you should somehow redesign your code to eliminate the need for that friend declaration and thus eliminate this dependency.Alternatively, you can resolve it by changing
D1.hand keepingD2.hunchanged. However, to follow that path you’ll have to replace your “fine-grained” friend declarationwith a more sweeping and permissive
and remove the inclusion of
D2.hfromD1.h.The former friend declaration requires class
D2to be complete, which is actually what creates an “unbreakable” dependency. The latter declaration does not requireD2to be complete.