正向声明要在基类中使用的派生类会导致缺少默认构造函数错误
forward declaring a derived class to be used in a base class causes a missing default constructor error
有一个复杂的程序,不断抛出丢失的默认构造函数错误,经过多次修补,我发现了完全相同的场景,也出现了相同的错误。这个怎么了?
class B;
class A
{
public:
A() {instance = new B;}
virtual ~A() {delete instance;}
private:
A*instance;
};
class B : public A
{
public:
B(){}
}
不能正向声明要在基类中使用的派生类吗?
如果编译器对类B
一无所知,new 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到底是什么?让基类实例化派生类确实有点不寻常。
您需要将A的构造函数的定义(但不是声明)放在A之外,放在B的定义之后。在A中使用B是可以的,只要您不需要它是完整的(完全定义的)-new B
肯定需要。
c++关于编译器向前看的规则并不明显(例如,在方法中使用instance
是可以的,即使稍后在类中定义了成员,但在同一源文件中使用稍后定义的类是不可以的)。
在这种情况下,问题(正如另一个报告的那样)是,当编译new B
时,编译器必须了解更多关于B
的信息,而不仅仅是它是一个类,并且它不会一直阅读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
的实例(B
的A
基本子对象)。
这意味着要创建A
的实例,您需要间接创建A
的实例。
听起来很古怪,不是吗?
使用此代码实例化A
(或B
)的实例将导致无限递归(即,在大多数实现中会出现奇怪的崩溃)。
否。因为派生类可能包含其他元素。所以您不能使用它来用派生类对象初始化基类对象。
相关文章:
- "error: no matching function for call to"构造函数错误
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 模板,函数使用错误的构造函数来复制我的对象
- C++ OpenCV 卡尔曼滤波器构造函数错误
- 不命名构造函数和析构函数上的类型错误
- 处理简单 cpp 类构造函数中的错误
- 类和构造函数中的函数根本不起作用,并且不返回任何错误
- 链接器错误:无法解析构造函数
- 当我尝试通过构造函数分配 char 数组时出现错误
- 没有参数的构造函数给我错误
- 使用复制构造函数的程序输出错误
- 默认构造函数上的分段错误
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 为什么定义复制构造函数会给我错误:无法将类型 'obj&' 的非常量左值引用绑定到类型为"obj"的右值?
- 带有 QWidget 的分段错误构造函数.Qt/C++
- C++错误构造函数参数
- 错误:构造函数未命名类型
- 错误:构造函数在此上下文中受到保护
- 没有匹配的函数错误C++构造函数
- 错误:构造函数的多个定义