错误:没有合适的默认构造函数

时间:2015-10-04 14:25:34

标签: c++ constructor default

无法编译以下内容。什么错了?

class B;
class A
{
public:
    void DoSomething()
    {
        ...
        B* myb = new B();
        ...
    }
};

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

4 个答案:

答案 0 :(得分:1)

new B()需要完整的类型定义。前瞻声明是不够的。

哪个有道理。例如,谁说B甚至有一个公共默认构造函数?在B的完整定义已知之前,您无法知道。

答案 1 :(得分:1)

您执行前向声明以了解某些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,依此类推。

答案 2 :(得分:0)

当您转发声明类型时,您告诉编译器存在这样的类型。但编译器不知道该类型的大小或成员。

您通常使用前向声明来打破循环依赖。

class B;
class A
{
public:
    void DoSomething()
    {
        ...
        B* myb ;            ...
    }
};

这将起作用,因为你只有一个指向该类型的指针。

这已在此详细讨论: forward reference usage

答案 3 :(得分:0)

class B;

上面的声明(前向声明)将名称 B 引入编译器。在声明之后和定义之前,键入 B 不完整类型

不完整类型的使用受到限制。例如,可以将指针或引用定义为这种类型。但是,这是不可能的;

  • 创建该类型的对象(编译器不知道类的大小)
  • 访问该类型的成员(编译器不知道该类具有哪个成员)

在相关代码中;

B* myb = new B();

是在声明之后和看到定义之前。