派生类错误:未定义类型

时间:2012-08-16 16:02:08

标签: c++

代码如下所示:

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

那么我做错了什么?感谢。

3 个答案:

答案 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.hint 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是什么。