在C ++中声明对象的问题

时间:2011-03-18 10:20:23

标签: c++ oop

我在下面有一个简单的代码:

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类之前。有什么想法吗?

4 个答案:

答案 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

http://www.codeguru.com/forum/showthread.php?t=358333(见第2条)

http://en.wikipedia.org/wiki/Forward_declaration

答案 3 :(得分:1)

C ++有一个“不完整”类的概念,这是你需要知道的。

在许多情况下,使用不完整的类可以让你只知道它是一个类,而不知道它是什么。

这使得类详细信息可以在以后更改而无需重新编译,因此它在耦合模型中的依赖性要弱得多。

您需要一个完整的课程:

  • 有一个实例。
  • 从中获取
  • 调用任何方法。
  • 删除指向它的指针。

您只需要一个不完整的课程:

  • 按住指针或引用它。
  • 将指针或引用传递给带有指针或引用的函数。 (这可以是删除指针的函数,只要它在该点完全定义)。

我认为你只需要一个不完整的类来声明一个返回一个的函数,并且可能声明一个函数将一个作为参数,但是在你定义或调用它需要完成的函数时,即使你不使用返回值。