C ++ - 两个类互相实例化,不能使用前向声明

时间:2012-11-13 17:37:06

标签: c++

我有A和B类,两个都有包含防护的头文件。一个人读到:

#ifndef A_H
#define A_H

#include "B.h"

class A
{
B b;
};

#endif

另一个:

#ifndef B_H
#define B_H

#include "A.h"

class B
{
A a;
};

#endif

现在我使用以下main.cpp测试它:

#include "A.h"

int main()
{
        A a;
}

编译错误如下:

# make main
g++     main.cpp   -o main
B.h:8: error: ‘A’ does not name a type

除了使用指针/引用和前向声明之外,是否有解决此问题的方法?

4 个答案:

答案 0 :(得分:4)

不,这是不可能的:其中一个需要是指针或引用:因为如果A包含B,其中包含A,其中包含B,那么您将获得无限递归并尝试指定无限大小的对象。 / p>

答案 1 :(得分:2)

遗憾的是,没有别的选择,除了使用指针/引用和转发声明。

答案 2 :(得分:1)

你不能这样做,你会导致无限递归(A会包含B,B会包括,A ...),加上编译器不允许它,因为在其中一个类声明中另一个类将是不完整的。 (未完全定义)

如果其中一个是指针或参考,你可以这样做。

答案 3 :(得分:1)

如果可能的话,我建议使用pImpl习语(指向实现,其他名称:不透明指针,Handle-body惯用法,Cheshire Cat ...有关详细信息,请参阅here。)

它基本上允许您从类的用户通常可见的实现细节中“释放”您的类声明(即使它们不可用,假设private访问)。

您只需按如下方式声明您的课程:

#ifndef A_H
#define A_H

class A{
public:
     //declare public methods -> "interface"
private:
     struct Private;
     Private * mp_d;  //feel free to use smart pointer
};

#endif

前向声明struct(或class)仅在源文件中定义,并包含所有实现详细信息,例如您的类内部的数据成员和函数。

#include "B.h"
struct A::Private {
      B a;
};


A::A() : mp_d( new Private()) {
} 

A::~A(){
    delete mp_d;   //not required if using smart pointer
}

NB:现在,编译器生成的复制构造函数和分配运算符不再起作用(如预期的那样)。确保要么自己实现它们,要么只是通过声明它们private来阻止编译器生成它们(没有实现)。 (这基本上是C ++ 03风格;我认为在C ++ 11中你只需在声明后添加= delete以防止编译生成。)

编辑:添加了pImpl的“长”名称