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 次 |
最近记录: |