此代码不做任何特殊操作。这只是一个用前向声明来表示问题的片段。只是一个简短的问题:为什么它不起作用以及如何强制它起作用?
class A;
class B {
A obj;
public:
int getB() const {
return 0;
}
void doSmth() {
int a = obj.getA();
}
};
class A {
B obj;
public:
int getA() const {
return 1;
}
void doSomething() {
int b = obj.getB();
}
};
这段代码给了我错误:
error C2079: 'B::obj' uses undefined class 'A'
error C2228: left of '.getA' must have class/struct/union
答案 0 :(得分:6)
前向声明只允许您使用指针和对象的引用。您正试图在类定义可用之前完全定义一个。
为了使这项工作,您应该将A中的obj更改为指针(可能不是最佳解决方案)或使用PIMPL惯用法(谷歌),这应该让您解决这个问题。
答案 1 :(得分:4)
你的构造根本没有意义。 A
或B
都不是明确定义的结构,因为它们包含无限递归的子对象序列。
您刚刚提出了一个与此问题相同的问题的模糊示例:
struct Box { Box hubert; };
同样,这种数据结构毫无意义。
如果你愿意的话,编程中的所有东西都必须是有限的和有根据的。
实际上,C ++通过要求类定义必须只包含具有完整类型的成员对象来禁止您尝试执行的操作。但它只是归结为具有逻辑意义。试想一下如何初始化这样的数据结构。 总是必须先来。
答案 2 :(得分:3)
在C ++中,这种类型的循环依赖是不可能的。您不能拥有彼此包含的对象。但是,您可以存储指针或引用。如果没有完整的定义,你也无法真正使用类的方法。
所以,你需要做两件事:
1)用指针替换对象。
2)在类定义之后实现方法。如果它们位于标题中,则您需要将其标记为inline
以防止出现多个定义。
class A;
class B {
std::shared_ptr<A> obj;
public:
int getB() const;
void doSmth();
};
class A {
std::shared_ptr<B> obj;
public:
int getA() const;
void doSomething();
};
inline int B::getB() const {
return 0;
}
inline void B::doSmth() {
int a = obj->getA();
}
inline int A::getA() const {
return 1;
}
inline void A::doSomething() {
int b = obj->getB();
}
答案 3 :(得分:1)
我认为您需要为obj A和obj B创建头文件来修复您的问题。当B被定义时,它只知道A不存在A所具有的函数/方法。
每个头文件都需要包含每个函数/方法的原型。例如:
class A{
int GetA() const;
void DoSomething();
}
格式可能已关闭(我习惯使用Obj C标题)但这应该会有所帮助。