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;
}
当我运行这个程序时,我似乎构造了两次 A 类,因为在我的控制台上“hello”被打印了两次。所以我的问题是我到底在哪里调用 A 的构造函数以及如何让它停止所以我只构造 A 一次,同时仍然将 A 对象传递给 B。
最佳答案
发生这种情况是因为您的 B
类包含 A
类型的成员。作为 B
构造的一部分,构造了 B::object
成员,这需要调用 A
构造函数。所以你实际上有两个 A
实例:object
和 bObject.object
。
因为你没有把 object
放在 B::B()
的初始化列表中,所以 B::object
是默认构造的. object = aObject;
然后分配给存储在 object
中的现有 A
。因此,您不是复制构造 B::object
,而是默认构造它(它负责您看到的第二个“hello”),然后为它分配一个新值。
编译器会为你提供一个复制构造函数A(const A &)
,所以你可以从参数中复制构造B::object
,像这样:
B(A aObject) : object(aObject) { }
这个构造函数不调用默认构造函数,也不包含默认构造函数中包含的代码。因此,调用此构造函数不会导致输出“hello”。
请注意,您仍然会构造一个新的 A
(实际上您会这样做两次,因为 aObject
是按值传递的)但是因为您没有定义复制构造函数,它不会包含将字符串写入 std::cout
的代码。
此处发生的相关事件的实际顺序是:
一个对象;
调用A::A()
构造函数。 (第一个“hello”是从这里打印出来的。)B bObject(object);
将调用B::B(A)
构造函数,但是因为A
参数被value,object
首先使用编译器生成的A::A(const A &)
复制构造函数复制到一个新的临时A
中。- 调用
B::B(A)
构造函数创建bObject
,传入上一步构造的临时A
。 - 在
B
构造函数内部,B::object
对象默认使用A::A()
构造,因为它是不在构造函数的初始化列表中。 (第二个“hello”是从这里打印出来的。) - 最后,运行
B::B(A)
构造函数的主体,它分配临时A
对象的值(存储在aObject
) 到B::object
中包含的A
,这是在前面的步骤中构造的。此分配是通过使用编译器生成的A & A::operator=(A const &)
运算符完成的。
关于c++ - 什么时候调用构造函数以及如何不调用它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26790560/