我在下面有一个简单的代码:
class B;
class A{
B b;
};
class B{
public:
B(){
}
};
在A类的定义中,我有一个B型属性。使用MS Visual Studio进行编译,我遇到以下错误:
error C2079: 'A::b' uses undefined class 'B'
由于某些原因,我无法将A类的定义放在A类之前。有什么想法吗?
答案 0 :(得分:12)
编译器已经告诉你出了什么问题:A有一个未定义类型的成员数据b。你的前瞻性声明:
class B;
就是:声明,而不是定义。由于A类直接包含B的实例(不仅仅是指向B的指针),编译器需要知道B的确切大小:它需要它的定义,而不仅仅是一个声明,即B在某个时刻存在的承诺。
这里最简单的方法是以这种方式重新排序:
class B{
public:
B(){
}
};
class A{
B b;
};
编辑:另请参阅this question了解声明与定义之间的区别。
进一步编辑:另一种方法是将您的成员数据更改为指针或引用。 请注意,这不是一个简单的语法更改:它会对对象的生命周期产生影响,因为A :: b指向的对象可能会在A的破坏后继续存在。
如果您想要的是构图(B是A的一部分并且与A一起死亡),使用指针将使您的生活变得更加困难而且收益甚微。
更多编辑(!):刚才意识到我误读了你问题的结尾;阻止你在A之前宣布B的原因是什么?
如果他们无法解决,你可能不得不走指针路线。这些原因可能表明您的对象太紧密了! (也许B需要是A的内部类?或者只是简单地合并到一个对象中?)
答案 1 :(得分:1)
class A;
class B {
A * getA();
};
class A {
B b;
};
这是解决此问题的典型方法。您必须拥有B的定义才能拥有B b;
成员。
你需要一个前向声明来声明一个B的引用/指针,你需要完整的定义才能用B做任何其他的事情(比如定义一个变量,调用一个成员函数等等)
答案 2 :(得分:1)
如果您将对b
的引用更改为指向B
的指针,则可以执行所需的操作。
class A{
B* bPtr;
};
class B{
public:
B(){
}
};
原则上,您不需要显式声明 - 也就是说,当您不需要实际大小时,只需要前向声明即可该类的类,或访问类中的类型和成员函数。
在原始示例中,您直接引用B
。因此,编译器需要知道有关B
的所有内容,因此需要显式声明而不是前向声明。
通过使用指向A
的{{1}}类声明,您可以获得前向声明。
修改强>
有些链接可能会为您解释这个概念:
http://www.goingware.com/tips/parameters/notrequired.html
http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
答案 3 :(得分:1)
C ++有一个“不完整”类的概念,这是你需要知道的。
在许多情况下,使用不完整的类可以让你只知道它是一个类,而不知道它是什么。
这使得类详细信息可以在以后更改而无需重新编译,因此它在耦合模型中的依赖性要弱得多。
您需要一个完整的课程:
您只需要一个不完整的课程:
我认为你只需要一个不完整的类来声明一个返回一个的函数,并且可能声明一个函数将一个作为参数,但是在你定义或调用它需要完成的函数时,即使你不使用返回值。