我得到错误:B没有合适的默认构造函数。但是,我不明白为什么编译器想调用默认构造函数,当我给出参数ii而DONT想调用默认值时。
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ii) { i = ii; cout << "Constructor for A\n"; }
~A() { cout << "Destructor for A\n"; }
void f() const{}
};
class B {
int i;
public:
B(int ii) { i = ii; cout << "Constructor for B\n"; }
~B() { cout << "Destructor for B\n"; }
void f() const{}
};
class C:public B {
A a;
public:
C() { cout << "Constructor for C\n"; }
~C() { cout << "Destructor for C\n"; }
void f() const {
a.f();
B::f();
}
};
class D:public B {
C c;
public:
D(int ii) { B(ii); cout << "Constructor for D\n"; }
~D() { cout << "Destructor for D\n"; }
};
int main() {
D d(47);
}
答案 0 :(得分:4)
应该在初始化列表中调用您的父构造函数:
class D:public B {
C c;
public:
D(int ii) : B(ii)/* <- */ { cout << "Constructor for D\n"; }
~D() { cout << "Destructor for D\n"; }
};
请注意/ *&lt; - * / comment。这需要改变。
您现在正在做的是在D类构造函数中创建一个B()实例,该构造函数未被使用:
D(int ii) { B(ii); /* <- useless*/ }
答案 1 :(得分:2)
D(int ii) { B(ii); cout << "Constructor for D\n"; }
调用B
的默认构造函数。 B(ii)
创建一个临时对象B
,一旦D
的构造函数返回就会被破坏,简而言之,它不会为正在构造的对象的Base类调用构造函数。 / p>
<强>解决方案:强>
为了能够调用Base类的特定构造函数,您应该使用 Member Initializer list 。
D(int ii) : B(ii)
{
}
答案 2 :(得分:1)
此代码:
class C:public B
{
C() { cout << "Constructor for C\n"; }
};
尝试调用B
的默认构造函数。
你可能想要:
class C:public B
{
C() : B(0) { cout << "Constructor for C\n"; }
};
但这取决于你的逻辑。
以下也是错误的:
D(int ii) { B(ii); cout << "Constructor for D\n"; }
应该是
D(int ii) : B(ii) { cout << "Constructor for D\n"; }
在子类构造函数的主体中调用基类构造函数只会创建一个不执行任何操作的临时对象。要获得您期望的行为,您必须在初始化列表中调用构造函数。
答案 3 :(得分:1)
你正在创建一个D,它是从B派生的 - 但是D的ctor没有将参数传递给B的构造函数,这需要B有一个默认的ctor。
要解决此问题,您通常需要编写D以向B的ctor提供参数:
class D : public B {
C C;
public:
D(int ii) : B(ii) { cout << "ctor for D\n"; }
};
答案 4 :(得分:1)
您需要意识到基础和成员子对象是在您进入构造函数体时构造的!也就是说,如果你有一个没有默认值的基数或成员,你需要在成员初始化列表中传递它的参数:
D(int ii): B(ii) { std::cout << "constructor for D\n"; }
您在D
构造函数体中构造的对象只是一个临时对象,在您的情况下并不真正起任何作用(临时对象在某些情况下可能很有用)。