0

代码如下所示:

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;}
}

我已经包含"B.h"在派生类的 .h 文件("D1.h" and "D2.h")和D2.hD1 中的“”中,"D1.h"在 D2 中......但不断收到编译错误:

...\D2.h ... use of undefined type D1

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

4

3 回答 3

3

您创建了一个循环包含:您包含D1.hD2.h并且您还包含D2.hD1.h. 循环包容永远不会奏效,也永远不会取得任何成就。

您的循环包含是类定义之间循环依赖的直接结果。在您的代码中,两个类定义以需要两个类类型都完整(完全定义)的方式相互引用。这意味着无论您做什么,都无法编译您的代码。您需要打破类定义之间的循环依赖关系。

在您的情况下,可以通过以下方式完成。

保持D1.h不变,即保持包含D2.hD1.h保持类的定义不变D1

但是,不要包含D1.hintoD2.h而是引入 into 的前向D1声明D2.h

class D1;

将定义更改D2

class D2: public B {
public:
  int get(D1& d);
};

注意:不要试图get在 class 的定义中定义正确的方法D2。您必须的定义重新定位D2::get到其他地方,其中完整的定义D1也是可见的(D2.cpp例如,应该同时包含D1.hD2.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.hfrom D1.h

以前的朋友声明要求类D2是完整的,这实际上是创建“牢不可破”的依赖关系的原因。后一个声明不需要D2完整。

于 2012-08-16T16:11:10.753 回答
0

在这一点上,代码提到D2了没有任何东西可以说明是什么D2(编译器并没有提前弄清楚)。因此,您需要通过在定义开始之前D2添加来告诉编译器是什么。class D2;D1

于 2012-08-16T16:07:48.530 回答
0

如果 D1 的定义依赖于 D2 并且 D2 的定义依赖于 D1,那么您需要前向引用这两个类:

class B;
class D1;
class D2;
于 2012-08-16T16:06:31.397 回答