Почему мы не можем отложить инициализацию члена класса конструктором не по умолчанию? - PullRequest
0 голосов
/ 11 февраля 2020

У меня есть класс, как показано ниже:

#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;
}

Конечно, программа не компилируется. И это из-за следующей ошибки

error: конструктор для 'MyClass' должен явно инициализировать член 'anotherClassObject', у которого нет конструктора по умолчанию

Вопрос:
Но почему? Почему я не могу отложить инициализацию ученика? Обходной путь должен иметь конструктор по умолчанию и задержка инициализировать его реальным конструктором позже? Это анти-паттерн, чтобы делать это таким образом?

Я знаю, что это можно решить, сделав MyClassAnother anotherClassObject указателем. Но я хочу иметь MyClassAnother anotherClassObject в качестве объекта-члена или ссылочного члена в этом случае.

1 Ответ

1 голос
/ 11 февраля 2020

Конструктор должен гарантировать, что все члены правильно построены и инициализированы, а этот не делает этого. Что произойдет, если вы забудете позвонить Func(), а затем получить доступ к objcect.anotherClassObject?

В общем, отложенная инициализация может рассматриваться как анти-паттерн и идет вразрез с идиомой RAII , которая гласит: эта конструкция объекта должна быть успешной, если и только если инициализация базовых ресурсов (MyClassAnother в данном случае) прошла успешно. Это хороший шаблон для подражания, потому что он предотвращает использование непригодных объектов вокруг, потому что они не смогли должным образом инициализироваться, или потому, что кто-то забыл выполнить свои отложенные шаги инициализации.

Если MyClass объекты фактически могут использоваться без MyClassAnother Например, вы можете заключить последний в std::unique_pointer (C ++ 11) или std::optional (C ++ 17).

Если MyClass объекты не могут использоваться без MyClassAnother экземпляр, вам нужно передать этот экземпляр конструктору или создать его в списке инициализатора конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...