我确信这是我的一些设计缺陷,主要是因为我来自Java背景。但事实就是如此。
以下是一般设置:
我有一个课程,可以说A
与#include "B.h"
#include "B.h"
class A {
// stuff
private:
B _b;
}
此外,我的课程B
包含#include "C.h"
#include "C.h"
class B {
// more stuff
private:
C::EnumType _cEnum;
}
最后我的课程C
有#include "A.h"
#include "A.h"
class C {
public:
C(A a);
enum EnumType {
// enum stuff
};
// more stuff
}
我该如何解决这个问题?我已经尝试了一些前瞻性声明的业务,但它似乎没有用,虽然我没有声称我做得正确。命名空间可能吗?
答案 0 :(得分:3)
在C中,你不需要包括A.只有其他两个标题需要你放在那里的include指令。
class A;
class C {
public:
C(A a);
enum EnumType {
// enum stuff
};
// more stuff
};
将C::C
的定义放入.cpp
文件中,然后可以包含A.h
。只有C::C
的定义需要其参数类型才能有定义。
答案 1 :(得分:2)
我尝试了一些前瞻性声明,但似乎无法正常工作
您没有向我们展示“似乎无法正常工作”,或者“它似乎无法正常工作”,但您的代码中有一个位置可以使用前向声明替换完整类型定义,而不能使用前导声明替换两个。
非静态数据成员必须是完整类型:
[C++11: 9.2/10]:
非static
(9.4)数据成员不得有不完整的类型。特别是,类C
不应包含类C
的非静态成员,但它可以包含指向类C
的对象的指针或引用。
因此,B
中的A
和C::EnumType
中的B
无法向前声明。
BTW: static
数据成员不是这种情况,可以向前宣布:
[C++11: 9.4.2/2]:
在其类定义中声明static
数据成员不是定义,除了cv-qualifiedvoid
之外,其类型可能不完整。
但是,成员函数声明中的参数类型也是如此,因此您可以在A
中转发声明C(A a)
:
class A;
class C {
public:
C(A a);
enum EnumType {
// enum stuff
};
// more stuff
};
#include
尽可能少地插入标题。
我确信这是我的一些设计缺陷,主要是因为我来自Java背景
我没有看到Java与它有任何关系但是,是的,你的设计在这些类彼此依赖的方式上似乎存在缺陷。也许C::EnumType
应该是B::EnumType
?尽量让你的课程更加独立。前向声明都很好,但是如果你解决了设计紧密耦合的根本问题,生活会更容易。
答案 2 :(得分:0)
@Lightness说 - 如果你使用'forward'定义声明A类,你不需要将a.h包含在C的编译单元中。只要把'A级;'进入标题,告诉编译器(和链接器)在以后确定A是什么。唯一的缺点是文件C不再知道A中的内容,所以你必须使用引用或指针。
另一种方法是将C分成两部分。嵌入其中的枚举是否有原因,而不是B的一部分?如果C和B共享枚举定义,那么它应该被拆分成一个单独的类,或者只是一个顶层的枚举。
当我得到这样的循环定义时,我会仔细检查我正在做什么。我总觉得我为自己做的事情太复杂了。