Reputation: 333
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.
Upvotes: 0
Views: 286
Reputation: 320531
You created a circular inclusion: you included D1.h
into D2.h
and you also included D2.h
into D1.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.h
unchanged, i.e. keep including D2.h
into D1.h
and keep the definition of class D1
as is.
However, do not include D1.h
into D2.h
Instead introduce a forward declaration of D1
into D2.h
class D1;
Change the definition of D2
to
class D2: public B {
public:
int get(D1& d);
};
Note: do not attempt to define method get
right in the definition of class D2
. You have to relocate the definition of D2::get
to some other place, where the full definition of D1
is also visible (like in D2.cpp
for example, which should include both D1.h
and D2.h
)
int D2::get(D1& d)
{
return d.a;
}
That's it. A side-effect of defining D2::get
this way is that it becomes non-inline. If you really want to keep it inline, you'll have to define it as
inline int D2::get(D1& d)
{
return d.a;
}
and 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.h
or something like that) and remember to include it after the D1.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.h
and keeping D2.h
unchanged. However, to follow that path you'll have to replace your "fine-grained" friend declaration
friend int D2::get(D1&);
with a more sweeping and permissive
friend class D2;
and remove the inclusion of D2.h
from D1.h
.
The former friend declaration requires class D2
to be complete, which is actually what creates an "unbreakable" dependency. The latter declaration does not require D2
to be complete.
Upvotes: 3
Reputation: 76315
At the point were the code mentions D2
there hasn't been anything to say what D2
is (the compiler doesn't look ahead to figure it out). So you need to tell the compiler what D2
is by adding class D2;
before the start of the definition of D1
.
Upvotes: 0
Reputation: 11567
If D1's definition depends on D2 and D2's definition depends on D1, then you need to forward reference both classes:
class B;
class D1;
class D2;
Upvotes: 0