错误:没有合适的默认构造函数
Error: no appropriate default constructor
无法编译以下内容。 这里有什么问题?
class B;
class A
{
public:
void DoSomething()
{
...
B* myb = new B();
...
}
};
class B
{
public:
B() {}
};
new B()
需要类型的完整定义。仅向前申报是不够的。
这是有道理的。例如,谁说B
甚至有一个公共默认构造函数?在知道B
的完整定义之前,你不可能知道这一点。
你做前向声明是为了知道一些class B
存在,尽管它还没有定义。在这种情况下,您甚至不需要这样做,因为class A
中没有 B
类型的成员。
只需声明 doSomething
方法,并在定义B
后定义它
class A {
...
void doSomething(); // declared
...
};
class B {
...
};
// define doSomething after defining class B or in the .cpp source file
void A::doSomething() {
B *myb = new B();
...
}
尽管通常您会使用头/源文件,因此将声明与定义分开会更实用。
编辑
如果 A 和 B 都相互引用,那么您需要在其中之一(或两者(中编写前向声明。
// A.h
class B;
class A {
...
B *_myB;
};
// A.cpp
#include "B.h"
void A::doSomething() {
_myB = new B();
}
// B.h
class A;
class B {
...
A *_myA;
};
// B.cpp
#include "A.h"
void B::doSomething() {
_myA = new A();
}
前向声明允许您具有指向该类型的指针,例如 B*
。但不是完整的B
类型,因为B
的大小是未知的,但B*
与任何其他指针的大小相同。
您可以通过在头文件中包含另一个类来使其中一个类存储完整类型,但不能同时包含两个类。
无论如何,如果可以包含依赖的完整类型,那就没有意义了。然后A
的实例将实例化一个成员B
而该成员又将实例化其成员A
,依此类推。
当您转发声明一个类型时,您是在告诉编译器存在这样的类型。但是编译器不知道该类型的大小或成员。
通常使用前向声明来中断循环依赖项。
class B;
class A
{
public:
void DoSomething()
{
...
B* myb ; ...
}
};
这将起作用,因为您只有一个指向该类型的指针。
这里已经详细讨论了这个问题:前向引用用法
class B;
上面的声明(前向声明(将名称 B 引入编译器。在声明之后和定义出现之前,类型 B 是不完整的类型。
不完整类型的使用受到限制。例如,可以将指针或引用定义为此类类型。但是,这是不可能的;
- 创建该类型的对象(编译器不知道类的大小(
- 访问该类型的成员(编译器不知道该类具有哪个成员(
在有问题的代码中;
B* myb = new B();
是在声明之后和定义之前。
相关文章:
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 初始化具有非默认构造函数的std::数组项的更好方法
- 具有默认模板类型的默认构造函数的类型推导
- 如何使用非默认构造函数实例化模板化类
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 声明没有默认构造函数的字段
- 没有默认构造函数作为模板参数的自定义比较器
- C++17 没有默认构造函数的地图放置(私有默认构造函数)
- 使用移动调用对等构造函数unique_ptr默认构造函数
- C++复制构造函数和默认构造函数
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 为什么即使我调用参数化构造函数也会调用默认构造函数?
- 具有非默认构造函数的单例类
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 如何处理没有默认构造函数但在另一个构造函数中构造的对象?
- 在C++中使用默认构造函数初始化对象的不同方法
- 在没有默认构造函数的情况下创建的派生对象
- 强制使用默认构造函数对成员进行未初始化的声明
- 使用默认构造函数初始化对象的不同方法
- 创建类类型的动态分配数组,其中类不得具有默认构造函数