c++ - 什么时候调用构造函数以及如何不调用它们

标签 c++ constructor

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 实例:objectbObject.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 的代码。

此处发生的相关事件的实际顺序是:

  1. 一个对象; 调用 A::A() 构造函数。 (第一个“hello”是从这里打印出来的。)
  2. B bObject(object); 将调用 B::B(A) 构造函数,但是因为 A 参数被value,object 首先使用编译器生成的 A::A(const A &) 复制构造函数复制到一个新的临时 A 中。
  3. 调用B::B(A) 构造函数创建bObject,传入上一步构造的临时A
  4. B 构造函数内部,B::object 对象默认使用 A::A() 构造,因为它是不在构造函数的初始化列表中。 (第二个“hello”是从这里打印出来的。)
  5. 最后,运行 B::B(A) 构造函数的主体,它分配临时 A 对象的值(存储在 aObject ) 到 B::object 中包含的 A,这是在前面的步骤中构造的。此分配是通过使用编译器生成的 A & A::operator=(A const &) 运算符完成的。

关于c++ - 什么时候调用构造函数以及如何不调用它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26790560/

相关文章:

java - 我应该为 Java 中的列表对象提供 setter 吗?

c++ - 在 C++ 类构造函数中传递对象实例(无法编译)

c++ - 0x80004005 和 0x80000008 的 HRESULT E_FAIL 错误有什么不同?

c++ - getline() 后的 For 循环不执行

c++ - 在磁盘上实现的 FIFO 队列(或堆栈),而不是 ram(最好在 C++ 中)

c# - 如何使用反射创建 C# 数组并仅输入信息?

java - Android自定义arrayadapter构造函数问题

Javascript/Jquery OOP 不继承属性

c++ - 在 Ubuntu 9.10 上使用 Qt 编译共享库

c++ - 执行 wcscpy_s 时 WCHAR 溢出