0

有一个复杂的程序不断抛出缺少的默认构造函数错误,经过多次修补,我发现完全相同的场景给出了相同的错误。这有什么问题?

class B;

class A
{
public:
    A() {instance = new B;}
    virtual ~A() {delete instance;}
private:
    A*instance;
};

class B : public A
{
public:
    B(){}
}

不能转发声明要在基类中使用的派生类?

4

4 回答 4

2

new B如果编译器对类一无所知,怎么能成功B呢?如果将成员函数实现移出类A定义下方的类B,它应该可以工作:

class A
{
public:
    A();
    virtual ~A();
private:
    A * instance;
};

class B : public A
{
public:
    B(){}
};

A::A()
{
    instance = new B;
}

A::~A()
{
    delete instance;
}

A 和 B 到底是什么?让基类实例化派生类确实有点不寻常。

于 2012-07-21T15:59:27.460 回答
0

您需要将 A 的构造函数的定义(但不是声明)放在 A 之外,在 B 的定义之后。在 A 中使用 B 是可以的,只要您不需要它是完整的(完全定义的) -new B肯定会.

于 2012-07-21T15:59:53.180 回答
0

关于编译器如何向前看的 c++ 规则并不明显(例如,instance即使成员在类中稍后定义,但可以在方法中使用,但不能使用稍后在同一源文件中定义的类) .

在这种情况下,问题(正如其他报告的那样)是编译时编译new B器必须了解B的不仅仅是它是一个类,它不会继续阅读该类A以查看 a 到底是什么B

一种可能的解决方案是将构造函数和析构函数的定义放在A后面(仍然将它们内联):

class B;

class A
{
public:
    A();
    virtual ~A();
private:
    A *instance;
};

class B : public A
{
public:
    B() {}
};

inline A::A() { instance = new B; }
inline A::~A() { delete instance; }

这会编译但不会正确运行,因为您在这里尝试做的确实很困惑。

要创建 的实例,A您需要创建 的实例B,但B它是 的特化A,因此当您创建实例时,B您还将创建A(的A 基础子对象)的实例B

这意味着要创建一个实例,A您需要间接创建一个A.

听起来很绕圈,不是吗?

使用此代码实例化A(或B)的实例将导致无限递归(即在大多数实现中出现奇怪的崩溃)。

于 2012-07-21T16:09:16.237 回答
-1

不,因为派生类可能包含其他元素。所以你不能用它来用派生类对象初始化基类对象。

于 2012-07-21T16:00:39.010 回答