继承:没有合适的默认构造函数可用

Inheritance: No appropriate default constructor available

本文关键字:默认 构造函数 继承      更新时间:2023-10-16

我得到错误:没有合适的默认构造函数用于B。然而,当我给出参数ii和DONT想要调用默认构造函数时,我不明白编译器为什么要调用默认构造函数。

#include <iostream>
using namespace std;
class A {
    int i;
public:
    A(int ii) { i = ii; cout << "Constructor for An"; }
    ~A() { cout << "Destructor for An"; }
    void f() const{}
};
class B {
    int i;
public:
    B(int ii) { i = ii; cout << "Constructor for Bn"; }
    ~B() { cout << "Destructor for Bn"; }
    void f() const{}
};
class C:public B {
    A a;
public:
    C() { cout << "Constructor for Cn"; }
    ~C() { cout << "Destructor for Cn"; }
    void f() const {
        a.f();
        B::f();
    }
};
class D:public B {
    C c;
public:
    D(int ii) { B(ii); cout << "Constructor for Dn"; }
    ~D() { cout << "Destructor for Dn"; }
};
int main() {
    D d(47);
}

应该在初始值设定项列表中调用父构造函数:

class D:public B {
    C c;
public:
    D(int ii) : B(ii)/* <- */ { cout << "Constructor for Dn"; }
    ~D() { cout << "Destructor for Dn"; }
};

注意/*<-*/议论这需要改变。

你现在正在做的是在你的D类构造函数中创建一个B()的实例,它没有被使用:

D(int ii) { B(ii); /* <- useless*/ }
D(int ii) { B(ii); cout << "Constructor for Dn"; }

调用B的默认构造函数。B(ii)创建了一个B的临时对象,一旦D的构造函数返回,该对象就会被销毁。简而言之,它不调用正在构建的对象基类的构造函数。

解决方案:
若要能够调用基类的特定构造函数,应使用成员初始化器列表

D(int ii) : B(ii)
{
}

此代码:

class C:public B
{
    C() { cout << "Constructor for Cn"; }
};

尝试调用B的默认构造函数。

你可能想要:

class C:public B
{
    C() : B(0) { cout << "Constructor for Cn"; }
};

但这取决于你的逻辑。

以下也是错误的:

 D(int ii) { B(ii); cout << "Constructor for Dn"; }

应该是

 D(int ii) : B(ii) { cout << "Constructor for Dn"; }

在子类构造函数的主体中调用基类构造函数只会创建一个不做任何事情的临时对象。若要获得所需的行为,必须调用初始值设定项列表中的构造函数。

您正在创建一个从B派生的D,但D的ctor没有将参数传递给B的构造函数,这需要B有一个默认的ctor。

为了解决这个问题,您通常需要编写D来为B的ctor:提供一个参数

class D : public B { 
    C C;
public:
    D(int ii) : B(ii) { cout << "ctor for Dn"; }
};

您需要意识到,在进入构造函数的主体时,基本子对象和成员子对象已经构造好了!也就是说,如果你有一个没有默认值的基或成员,你需要在成员初始值设定项列表中传递它的参数:

D(int ii): B(ii) { std::cout << "constructor for Dn"; }

您在D构造函数的主体中构建的对象只是一个临时对象,在您的情况下并没有真正起到任何作用(不过,在某些情况下,临时对象可能很有用)。