有一个复杂的程序不断抛出缺少的默认构造函数错误,并经过大量的修改后,我发现了完全相同的情况,给出了相同的错误。这有什么问题?
class B;
class A
{
public:
A() {instance = new B;}
virtual ~A() {delete instance;}
private:
A*instance;
};
class B : public A
{
public:
B(){}
}
无法转发声明要在基类中使用的派生类吗?
答案 0 :(得分: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究竟是什么?让基类实例化派生类肯定有点不寻常。
答案 1 :(得分:0)
在B的定义之后,您需要将A的构造函数的定义(但不是声明)放在A之外。只要您不需要它完整(完全定义),在A中使用B就可以了 - 而new B
肯定会。
答案 2 :(得分:0)
instance
。稍后在同一源文件中定义。)
在这种情况下,问题(正如其他报道的那样)是在编译new B
时编译器必须知道更多关于B
而不仅仅是一个类,并且它不会继续读取类A
1}}看看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
的特化,因此当您创建{的实例时{1}}您还将创建B
(A
的{{1}} 基础子对象)的实例。
这意味着要创建A
的实例,您需要间接创建B
的实例。
听起来很吵,不是吗?
使用此代码实例化A
(或A
)的实例将导致无限递归(即大多数实现中的奇怪崩溃)。
答案 3 :(得分:-1)
没有。因为派生类可能包含其他元素。所以你不能用它来用派生类对象初始化基类对象。