为什么我们不能延迟使用非默认构造函数初始化 class 成员?

Why cant we delay initialise a class member with a non default constructor?

我有一个 class 如下所示:

#pragma once
#include <atomic>

class MyClassAnother {
public:
    MyClassAnother(int val) : m_val(val) {
    }

private:
    int m_val;
};

还有一个 class 持有对象 MyClassAnother

#pragma once
#include "MyClassAnother.hpp"

class MyClass {
public:
    MyClass() {

    }

    void Func() {
        anotherClassObject = MyClassAnother(2);
    }

private:
    MyClassAnother anotherClassObject;
};

这里是 main.cpp

#include "MyClass.hpp"
#include <iostream>

int main() {
   MyClass object;
}

程序当然编译不过。这是因为以下错误

error: constructor for 'MyClass' must explicitly initialize the member 'anotherClassObject' which does not have a default constructor

问题:
但为什么?为什么我不能延迟初始化 class 成员?解决方法是使用默认构造函数并稍后使用真正的构造函数延迟初始化它吗?那么这样做是反模式吗?

我知道这可以通过使 MyClassAnother anotherClassObject 成为一个指针来解决。但在这种情况下,我想将 MyClassAnother anotherClassObject 作为成员对象或引用成员。

构造函数必须保证所有成员都被正确构造和初始化,而这个构造函数不这样做。如果您忘记调用 Func() 然后访问 objcect.anotherClassObject 会怎样?

一般来说,延迟初始化可以被认为是一种反模式,并且违反了 RAII idiom,它指出当且仅当底层资源初始化时对象构造应该成功(MyClassAnother例)成功。这是一个很好的模式,因为它可以防止由于无法正确初始化或有人忘记执行延迟初始化步骤而导致无法使用的对象。

如果 MyClass 对象在没有 MyClassAnother 实例的情况下实际上可用,您可以将后者包装在 std::unique_pointer (C++11) 或 std::optional ( C++17).

如果 MyClass 对象在没有 MyClassAnother 实例的情况下无法使用,您需要将该实例传递给构造函数,或者在构造函数的初始化列表中创建它。