代码如下所示:
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;}
}
我在两个派生类'.h文件("B.h"
)和D1中的“"D1.h" and "D2.h"
”,D2中的D2.h
中包含"D1.h"
但是...继续编译错误:
...\D2.h ... use of undefined type D1
那么我做错了什么?感谢。
答案 0 :(得分:2)
您创建了一个循环包含:您将D1.h
包含到D2.h
中,并且还将D2.h
添加到D1.h
中。循环包含永远不会起作用,也永远无法实现。
您的循环包含是您的类定义之间循环依赖的直接结果。在您的代码中,两个类定义以一种需要两种类型完整(完全定义)的方式相互引用。这意味着无论您执行什么操作,都无法编译您的代码。您需要打破类定义之间的循环依赖。
在您的情况下,可以通过以下方式完成。
保持D1.h
不变,即继续将D2.h
包含在D1.h
中,并按原样保留D1
类的定义。
但是,不将D1.h
包含到D2.h
中而是将D1
的前瞻性声明引入D2.h
class D1;
将D2
的定义更改为
class D2: public B {
public:
int get(D1& d);
};
注意:请勿尝试在类get
的定义中定义方法D2
。您必须将D2::get
的定义重新定位到其他地方,其中D1
的完整定义也是可见的(例如D2.cpp
中的D1.h
包括D2.h
和int D2::get(D1& d)
{
return d.a;
}
)
D2::get
就是这样。以这种方式定义inline int D2::get(D1& d)
{
return d.a;
}
的副作用是它变为非内联。如果你真的想让它保持内联,你必须将其定义为
D1
并确保在 D2_aux.h
的完整定义之后仅以某种方式包含。例如,您可以将其放入第三个标题文件(D1.h
或类似标题文件),并记住在 D1
之后将其包含在中。
当然,尝试解决此问题的更好方法是重新考虑整个设计。你真的需要D1.h
内的朋友声明吗?也许你应该以某种方式重新设计你的代码,以消除对朋友声明的需要,从而消除这种依赖。
或者,您可以通过更改D2.h
并保持friend int D2::get(D1&);
不变来解决此问题。但是,要遵循这条路径,您必须更换“细粒度”的朋友声明
friend class D2;
有更广泛和宽容的
D2.h
并从D1.h
中删除D2
。
前朋友声明要求类D2
完整,这实际上是创建“牢不可破”的依赖。后一声明不需要{{1}}完成。
答案 1 :(得分:0)
如果D1的定义取决于D2而D2的定义取决于D1,那么你需要转发参考两个类:
class B;
class D1;
class D2;
答案 2 :(得分:0)
当时代码提到了D2
,没有任何东西可以说明D2
是什么(编译器没有预先弄明白)。因此,您需要在D2
定义开始之前添加class D2;
,告诉编译器D1
是什么。