J'ai une classe comme ci-dessous:

#pragma once
#include <atomic>

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

private:
    int m_val;
};

Il existe une autre classe qui détient un objet à MyClassAnother

#pragma once
#include "MyClassAnother.hpp"

class MyClass {
public:
    MyClass() {

    }

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

private:
    MyClassAnother anotherClassObject;
};

Et voici le main.cpp

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

int main() {
   MyClass object;
}

Bien sûr, le programme ne compile pas. Et c'est à cause de l'erreur suivante

erreur : le constructeur de 'MyClass' doit initialiser explicitement le membre 'anotherClassObject' qui n'a pas de constructeur par défaut

Question :
Mais pourquoi? Pourquoi ne puis-je pas retarder l'initialisation du membre de la classe ? La solution de contournement consiste-t-elle à avoir un constructeur par défaut et à retarder son initialisation avec le vrai constructeur plus tard ? Est-ce un anti-modèle de procéder ainsi ?

Je sais que cela peut être résolu en faisant de MyClassAnother anotherClassObject un pointeur. Mais je veux avoir MyClassAnother anotherClassObject comme objet membre ou comme membre de référence dans ce cas.

0
AdeleGoldberg 11 févr. 2020 à 10:24

1 réponse

Meilleure réponse

Le constructeur doit garantir que tous les membres sont correctement construits et initialisés, et celui-ci ne le fait pas. Que se passe-t-il si vous oubliez d'appeler Func() puis d'accéder à objcect.anotherClassObject ?

L'initialisation retardée en général pourrait être considérée comme un anti-modèle et va à l'encontre de l'idiome RAII, qui indique que la construction de l'objet doit réussir si et seulement si l'initialisation des ressources sous-jacentes (MyClassAnother dans ce cas) a réussi. C'est un bon modèle à suivre, car cela évite d'avoir des objets inutilisables parce qu'ils n'ont pas réussi à s'initialiser correctement, ou parce que quelqu'un a oublié d'effectuer les étapes d'initialisation retardées.

Si les objets MyClass sont réellement utilisables sans instance MyClassAnother, vous pouvez envelopper cette dernière dans un std::unique_pointer (C++11) ou un std::optional (C++17) .

Si les objets MyClass ne sont pas utilisables sans une instance MyClassAnother, vous devez passer cette instance au constructeur ou la créer dans la liste d'initialisation du constructeur.

1
Thomas 11 févr. 2020 à 07:40