web-dev-qa-db-fra.com

Le membre par défaut valorise les meilleures pratiques

Est-ce une bonne pratique lors de l'écriture de code C++ 11 de définir les valeurs par défaut des membres de la classe dans le fichier d'en-tête de la classe?

Ou est-il préférable de faire cela dans le constructeur de la classe?

MODIFIER:

Je veux dire:

foo.h:

#include <string>

using std::string;

class Foo{
    private:
        string greet = "hello";
    public:
        Foo();
};

CONTRE

foo.cpp (bien sûr avec le fichier d'en-tête nécessaire, mais sans l'initialisation en classe):

Foo::Foo(){
    greet = "hello";
}

Lequel est le meilleur et pourquoi?

62
Paul

Si un membre de la classe est toujours initialisé avec la même valeur initiale, vous devez alors initialiser l’initialiseur en ligne afin d’éviter les doublons. Si la valeur initiale dépend du constructeur, placez-la dans la liste des initialiseurs du constructeur. (Et n'utilisez jamais de mission comme vous l'avez fait.)

Exemple:

class Foo
{
    bool done = false;   // always start like this
    int qty;
    Bar * p;

public:
    Foo()                        : qty(0),              p(nullptr)    { }
    Foo(int q, Bar * bp)         : qty(q),              p(bp)         { }
    explicit Foo(char const * s) : qty(std::strlen(s)), p(new Bar(s)) { }

    // ...
};

Dans cet exemple hypothétique, le membre done doit toujours démarrer en tant que false, il est donc préférable d'écrire l'initialiseur en ligne. Les deux autres membres, qty et p, peuvent être initialisés différemment dans chacun des trois constructeurs. Ils sont donc initialisés dans les listes d'initialisation des constructeurs.

Une curiosité: Notez que fournir un initialiseur en ligne empêche votre classe d’avoir un constructeur trivial par défaut.

77
Kerrek SB

Cela dépend si vous devez rester compatible avec les anciens compilateurs C++. Lorsque vous n'utilisez pas C++ 11, vous devez initialiser la plupart des membres (tous non statiques) du constructeur. De plus, de nombreuses personnes recommandent d'initialiser explicitement chaque membre, même si cela implique d'appeler explicitement le ctor par défaut. Habituellement, vous devriez placer les détails d’implémentation dans un fichier cpp pas dans le fichier d’en-tête, un exemple serait:

Example:
//foo.h

class Foo{
public: 
  Foo();
private:
  std::vector<int> vect;
};

//foo.cpp

Foo::Foo():vect(){
}

En C++ 11, vous avez plus de choix et l'initialiseur de classe devient très pratique, surtout si vous avez plusieurs cors. Voici un bon lien pour plus d'informations: http://www.stroustrup.com/C++11FAQ.html#member-init

Après édition: Selon votre code, vous utilisez C++ 11. À ma connaissance, il existe peu d'informations sur les bonnes pratiques concernant les nouvelles possibilités, mais à mon humble avis, l'initialiseur de classe est très pratique pour concentrer l'initialisation à un seul endroit, ce qui réduit la complexité et le typage.

11
Martin

L'initialisation dans les en-têtes présente les principaux avantages de garder le code plus local et facile à comprendre. Cela évite aussi de taper.

À mon avis, le principal inconvénient est la nécessité d'inclure plus d'en-têtes pour avoir accès aux constructeurs. Une simple déclaration en aval ne suffit pas, la compilation prend plus de temps.

2
Christopher Oezbek