提问人:Eds 提问时间:3/23/2022 最后编辑:ChristianEds 更新时间:3/23/2022 访问量:389
为什么用户定义的复制构造函数调用基本构造函数,而默认复制构造函数不调用?[复制]
Why is user defined copy constructor calling base constructor while default copy constructor doesn't? [duplicate]
问:
请看以下示例:
class A
{
public:
A()
{
cout<<"constructor A called: "<<this<<endl;
};
A(A const& other) = default;
};
class B : public A
{
public:
B()
{
cout<<"constructor B called: "<<this<<endl;
};
//This calls A's constructor
B(B const& other)
{
cout<<"B copy constructor called: "<<this<<endl;
};
//While this doesn't call A's constructor
//B(B const& other) = default;
};
int main()
{
B b;
B b2(b);
cout<<"b: "<<&b<<endl;
cout<<"b2: "<<&b2<<endl;
return 0;
}
输出:
constructor A called: 0x7fffc2fddda8
constructor B called: 0x7fffc2fddda8
constructor A called: 0x7fffc2fdddb0
B copy constructor called: 0x7fffc2fdddb0
b: 0x7fffc2fddda8
b2: 0x7fffc2fdddb0
为什么在复制 B 时调用 A 的构造函数? 不应该改用 A 的复制构造函数吗?
但是,如果将类 B 的复制构造函数更改为默认值,则在复制时不会调用 A 的构造函数,这是有道理的。
如果有人能给出合理的解释,那就太好了。
答:
3赞
Remy Lebeau
3/23/2022
#1
为什么在复制 B 时调用 A 的构造函数?不应该改用 A 的复制构造函数吗?
不,不应该。
派生类必须始终初始化基类。如果派生类具有由用户显式实现的构造函数,但它未在其成员初始化列表中显式调用基类构造函数,则编译器将对基类的默认构造函数进行隐式调用,而不考虑派生构造函数的类型。编译器不会对用户在实现派生构造函数时的意图做出任何假设。如果用户希望调用特定的基类构造函数,则需要自己进行该调用。
由于显式实现的复制构造函数缺少成员初始化列表,因此编译器通过调用其默认构造函数(而不是其复制构造函数)进行初始化。B
A
哎呀,这个:
B(B const& other)
{
...
}
等价于:
B(B const& other) : A()
{
...
}
不是这样,正如你所想的那样:
B(B const& other) : A(other)
{
...
}
但是,如果将类 B 的复制构造函数更改为默认值,则在复制时不会调用 A 的构造函数,这是有道理的。
正确,'ed copy 构造函数将调用基类的复制构造函数,而不是其默认构造函数。编译器隐式实现整个派生构造函数,因此它将选择要调用的适当的基类构造函数。default
评论
0赞
Eds
3/23/2022
多谢。现在这是有道理的。
评论
B(B const& other) { ... }
不要求复制构造函数。那将是B(B const& other): A(other) { ... }