为什么用户定义的复制构造函数调用基本构造函数,而默认复制构造函数不调用?[复制]

Why is user defined copy constructor calling base constructor while default copy constructor doesn't? [duplicate]

提问人:Eds 提问时间:3/23/2022 最后编辑:ChristianEds 更新时间:3/23/2022 访问量:389

问:

请看以下示例:

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 的构造函数,这是有道理的。

如果有人能给出合理的解释,那就太好了。

C++ 继承 复制构造函数

评论

3赞 πάντα ῥεῖ 3/23/2022
适当的基类构造函数总是在派生类构造函数之前调用。我不完全理解你的担忧?
0赞 Eds 3/23/2022
@πάνταῥεῖ我已经编辑了我的问题,我希望它现在更有意义
1赞 user4581301 3/23/2022
B(B const& other) { ... }不要求复制构造函数。那将是B(B const& other): A(other) { ... }
0赞 Eds 3/23/2022
@user4581301 确定会调用 A 的复制构造函数,而不会调用 A 的构造函数,对吧?
1赞 JaMiT 3/23/2022
这回答了你的问题吗?为什么隐式复制构造函数调用基类复制构造函数,而定义的复制构造函数不调用?或者也许如何在派生类中声明复制构造函数,而在基中没有默认构造函数?

答:

3赞 Remy Lebeau 3/23/2022 #1

为什么在复制 B 时调用 A 的构造函数?不应该改用 A 的复制构造函数吗?

不,不应该。

派生类必须始终初始化基类。如果派生类具有由用户显式实现的构造函数,但它未在其成员初始化列表中显式调用基类构造函数,则编译器将对基类的默认构造函数进行隐式调用,而不考虑派生构造函数的类型。编译器不会对用户在实现派生构造函数时的意图做出任何假设。如果用户希望调用特定的基类构造函数,则需要自己进行该调用。

由于显式实现的复制构造函数缺少成员初始化列表,因此编译器通过调用其默认构造函数(而不是其复制构造函数)进行初始化。BA

哎呀,这个:

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
多谢。现在这是有道理的。