首页 > 解决方案 > 为什么我们不能延迟使用非默认构造函数初始化类成员?

问题描述

我有一个像下面这样的课程:

#pragma once
#include <atomic>

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

private:
    int m_val;
};

还有另一个类持有一个对象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;
}

当然程序不会编译。并且由于以下错误

错误:“MyClass”的构造函数必须显式初始化没有默认构造函数的成员“anotherClassObject”

问:
但是为什么呢?为什么我不能延迟初始化类成员?是否有一个默认构造函数并延迟使用真正的构造函数初始化它?那么这样做是一种反模式吗?

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

标签: c++11constructordefault-constructor

解决方案


构造函数必须保证所有成员都正确构造和初始化,而这个不这样做。如果您忘记打电话Func()然后访问会发生什么objcect.anotherClassObject

一般来说,延迟初始化可以被认为是一种反模式,并且违反了RAII 习惯用法,它指出当且仅当底层资源的初始化(MyClassAnother在这种情况下)成功时,对象构造才应该成功。这是一个很好的模式,因为它可以防止周围出现不可用的对象,因为它们未能正确初始化,或者因为有人忘记执行他们延迟的初始化步骤。

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

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


推荐阅读