这是我的代码。
删除第11行时,输出为
A(0)
B(0)
A(1)
关于最后一行“ A(1)”,为什么要调用类A的第二个构造函数?
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A(0)" << endl; }
A(const A& a) { cout << "A(1)" << endl; }
};
class B {
public:
B() : a() { cout << "B(0)" << endl; }
// B(const B& b) { cout << "B(1)" << endl; }
private:
A a;
};
int main() {
B object1;
B object2 = object1;
return 0;
}
A(0)
B(0)
A(1)
答案 0 :(得分:7)
何时
B(const B& b) { cout << "B(1)" << endl; }
被注释掉/删除,编译器会为您生成一个副本构造函数。提供的复制构造函数将复制该类的所有成员,因此在这种情况下,它将删除一个看起来像
的复制构造函数B(const B& copy) : a(copy.a) {}
这就是为什么看到a
的副本构造函数的原因。
当您不评论/删除
B(const B& b) { cout << "B(1)" << endl; }
您不要复制a
,因为您没有告诉它这样做。编译器所做的是通过将构造函数转换为
B(const B& b) : a() { cout << "B(1)" << endl; }
因此将调用默认构造函数,而不是复制构造函数。
答案 1 :(得分:1)
编译器正在为您生成一个copy constructor,它将复制成员a
。为了复制成员a
,它依次调用其复制构造函数,并打印A(1)
。
答案 2 :(得分:0)
因为object2
是用B的隐式副本构造函数初始化的。一个隐式副本构造函数隐式复制该类的所有数据成员,因此调用了A的副本构造函数,它显示“ A(1) “。
答案 3 :(得分:0)
B类的编译器(带有注释的副本构造函数)隐式定义了默认的副本构造函数,该默认副本构造函数调用类成员的副本构造函数。
根据C ++ 20标准(11.3.4.2复制/移动构造函数)
14非工会类的隐式定义的复制/移动构造函数 X对它的基础和成员执行成员复制/移动...
B类的隐式定义的默认副本构造函数看起来像
B( const B &b ) : a( b.a )
{
}
这是一个演示程序
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A(0)" << endl; }
A(const A& a) { cout << "A(1)" << endl; }
};
class B {
public:
B() : a() { cout << "B(0)" << endl; }
// An analogy of the implicitly declared copy constructor
B(const B& b) : a( b.a ){}
private:
A a;
};
int main() {
B object1;
B object2 = object1;
return 0;
}
程序输出将与删除与编译器隐式生成的副本构造函数相对应的类B的副本构造函数相同。
A(0)
B(0)
A(1)
答案 4 :(得分:0)
您遇到的问题与思考注释第11行有关,意味着您已删除该构造函数。
在C ++中,即使最终没有使用它们,也会自动生成一些构造函数,即使您自己没有声明它们。具有与B中注释掉的构造器相同的签名的复制构造器就是其中之一。
在您的情况下,您最终要首先调用B的默认构造函数,该构造函数也首先使用默认构造函数构造它的成员A。这应该给出您所看到的输出,由于成员初始化顺序,在A的副本构造函数的主体之前到达B的主体。
然后,使用赋值运算符创建一个类型为B的新对象,该运算符隐式调用现在生成的B的副本构造函数。这意味着A的副本构造函数也被调用,这是B的副本构造函数如何使用的规则自动生成。取消注释A的复制构造函数,然后使用打印输出调用它。