class A
{
public:
A(){std::cout << "hello\n";}
};
class B
{
A object;
public:
B(A aObject){ object = aObject;}
};
int main() {
A object;
B bObject(object);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我运行这个程序时,似乎我构造了两次A类,因为在我的控制台上"hello"被打印两次.所以我的问题是我究竟是在为A调用我的构造函数以及如何使它停止所以我只构造一次A,同时仍然将A对象传递给B.
发生这种情况是因为您的B类包含类型的成员A.作为结构的一部分B,该B::object构件被构造,这需要对一个呼叫A的构造.所以你实际上有两个A实例:object和bObject.object.
因为你没有把object中B::B()的初始化列表,B::object是缺省构造. object = aObject;然后分配给现有的A存储object.因此,不是复制构造B::object,而是默认构造它(它负责你看到的第二个"你好"),然后为它分配一个新值.
编译器将为您提供一个拷贝构造函数A(const A &),因此您可以B::object从参数中复制构造,如下所示:
B(A aObject) : object(aObject) { }
Run Code Online (Sandbox Code Playgroud)
此构造函数不调用默认构造函数,也不包含默认构造函数中包含的代码.因此,调用此构造函数不会导致输出"hello".
请注意,您仍然会构造一个新的A(事实上,您将这样做两次,因为它aObject是按值传递的),但由于您没有自己定义复制构造函数,因此它不会包含将字符串写入的代码std::cout.
这里发生的相关事件的实际顺序是:
A object;调用A::A()构造函数. (第一个"你好"是从这里打印出来的.)B bObject(object);将调用B::B(A)构造函数,但由于A参数是由值接受的,object因此首先A使用编译器生成的A::A(const A &)复制构造函数将其复制到新的临时文件中.B::B(A)构造函数被调用来创建bObject,传递临时A在最后一步构建.B构造函数内部,B::object对象是默认构造的,A::A()因为它不在构造函数的初始化列表中. (第二个"你好"是从这里打印出来的.)B::B(A)运行构造函数的主体,它将临时A对象(存储在其中aObject)的值分配给在前一步骤中构造的A包含的B::object内容.通过使用编译器生成的A & A::operator=(A const &)运算符完成此赋值.| 归档时间: |
|
| 查看次数: |
83 次 |
| 最近记录: |