93 votes

Meilleure pratique des valeurs par défaut des membres

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

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

EDIT :

Je veux dire :

foo.h :

#include <string>

using std::string;

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

VS

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

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

Laquelle est la meilleure et pourquoi ?

111voto

Kerrek SB Points 194696

Si un membre d'une classe est toujours initialisé avec la même valeur initiale, vous devez faire en sorte que l'initialisateur soit inline, afin d'éviter la duplication. Si la valeur initiale dépend du constructeur, alors mettez-la dans la liste des initialisateurs du constructeur. (Et n'utilisez jamais l'affectation de la manière dont 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'initialisateur en ligne. Les deux autres membres, qty y p peuvent être initialisés différemment dans chacun des trois constructeurs différents, ils sont donc initialisés dans les listes d'initialisation des constructeurs.

A curiosum : Notez que le fait de fournir un initialisateur en ligne empêche votre classe d'avoir un objet de type <em>constructeur trivial par défaut </em>.

13voto

Martin Points 1666

Si vous n'utilisez pas C++11, vous devez initialiser la plupart des membres (tous non statiques) dans le constructeur. De plus, de nombreuses personnes préconisent d'initialiser explicitement chaque membre, même si cela implique d'appeler explicitement le constructeur par défaut. En général, les détails de l'implémentation doivent être placés dans un fichier cpp et non dans le fichier d'en-tête, comme par exemple

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'initialisateur de membre de classe deviendra 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 l'édition : D'après votre code, vous utilisez C++11. A ma connaissance, il n'y a que peu d'informations sur les bonnes pratiques concernant les nouvelles possibilités mais, à mon avis, les initialisateurs de membres de classe sont très pratiques pour concentrer l'initialisation à un seul endroit, ce qui réduit la complexité et la saisie.

5voto

Christopher Oezbek Points 2691

L'initialisation dans les en-têtes a pour principal avantage de garder le code plus local et facile à comprendre. Elle permet également d'économiser un peu de frappe.

Le principal inconvénient, à mon avis, est la nécessité d'inclure plus d'en-têtes pour avoir accès aux constructeurs. La simple déclaration forward ne suffira pas, ce qui rendra la compilation plus longue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X