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

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

考虑以下示例:

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 的 复制构造函数吗?

但是,如果将classB的拷贝构造函数改为默认,A的构造函数不被调用时复制有意义。

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

Why is the constructor of A is called when copying B? Shouldn't the copy constructor of A be called instead?

不,不应该。

派生 class 必须始终初始化基 class。如果派生的 class 有一个由用户显式实现的构造函数,但它没有在其 member initialization list 中显式调用基 class 构造函数,编译器将隐式调用基class的默认构造函数,不管派生构造函数的类型。编译器不会对用户实现派生构造函数的意图做出任何假设。如果用户想要调用特定的基础 class 构造函数,他们需要自己进行调用。

由于 B 有一个显式实现的复制构造函数,它缺少成员初始化列表,编译器通过调用它的 default 构造函数来初始化 A,而不是它的构造函数复制构造函数。

哇,这个:

B(B const& other)
{
    ...
}

相当于:

B(B const& other) : A()
{
    ...
}

不像你想的那样:

B(B const& other) : A(other)
{
    ...
}

However, if you change class B's copy constructor to be default, the constructor of A is not called when copying which makes sense.

正确,default 复制构造函数将调用基础 class 的复制构造函数,而不是其默认构造函数。编译器正在隐式实现 entire 派生构造函数,因此它将选择适当的基础 class 构造函数来调用。