c++11 - 为什么我们不能延迟使用非默认构造函数初始化类成员?
问题描述
我有一个像下面这样的课程:
#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
作为成员对象或引用成员。
解决方案
构造函数必须保证所有成员都正确构造和初始化,而这个不这样做。如果您忘记打电话Func()
然后访问会发生什么objcect.anotherClassObject
?
一般来说,延迟初始化可以被认为是一种反模式,并且违反了RAII 习惯用法,它指出当且仅当底层资源的初始化(MyClassAnother
在这种情况下)成功时,对象构造才应该成功。这是一个很好的模式,因为它可以防止周围出现不可用的对象,因为它们未能正确初始化,或者因为有人忘记执行他们延迟的初始化步骤。
如果MyClass
对象实际上可以在没有MyClassAnother
实例的情况下使用,则可以将后者包装在std::unique_pointer
(C++11) 或std::optional
(C++17) 中。
如果MyClass
对象在没有MyClassAnother
实例的情况下不可用,则需要将该实例传递给构造函数,或者在构造函数的初始化列表中创建它。
推荐阅读
- outlook - Office 365 是否支持独立的 MAPI 调用
- php - 有什么办法可以两次包含相同的php文件?
- javascript - Google Maps GeoCode API 返回 NO_RESULTS 以按 PostalCode 进行搜索,但未指定地区/国家
- ios - 尝试使用 Firebase 动态链接,无法在 iOS 上打开应用
- windows - Git:无法使用 cygwin 构建带有冒号的文件夹
- ruby-on-rails - ActiveRecord - 复制连接表
- amazon-cloudformation - CloudFormation 秘密
- flutter - 在 Flutter 中调用绘图后保存在画布上绘制的像素的方法?
- meteor - 验证空格键 HTML 语法是否正确
- mysql - 如果结果子集不包含所需的日期,您如何过滤掉它?