50 votes

Quel est l'intérêt de supprimer le constructeur de classe par défaut?

Je prépare mon examen CPP et l'une des questions est la suivante: pouvez-vous supprimer le constructeur de classe par défaut et, dans l'affirmative, quelle serait la raison de le faire? OK, vous pouvez évidemment le faire:

 class MyClass 
{ 
  public: 
    MyClass() = delete; 
};
 

mais je ne comprends pas pourquoi voudriez-vous le faire?

75voto

Quentin Points 3904

Considérons la classe suivante:

struct Foo {
    int i;
};

Cette classe est un agrégat, et vous pouvez créer une instance avec tous les trois de ces définitions:

int main() {
    Foo f1;     // i uninitialized
    Foo f2{};   // i initialized to zero
    Foo f3{42}; // i initialized to 42
}

Maintenant, disons que vous n'aimez pas les valeurs non initialisées et les comportements indéfinis qu'elles pourraient produire. Vous pouvez supprimer le constructeur par défaut de Foo:

struct Foo {
    Foo() = delete;
    int i;
};

Foo est encore un agrégat, mais seulement les deux dernières définitions sont valables -- la première est maintenant une erreur de compilation.

46voto

Arnav Borborah Points 7947

Il ya quelques raisons pour supprimer le constructeur par défaut.

  1. La classe est purement statique, et vous ne voulez pas que les utilisateurs de l'instanciation d'une classe avec seulement des méthodes statiques/membres. Un exemple d'une telle classe peut être celui qui met en œuvre l'usine modèle de conception en utilisant uniquement des méthodes statiques pour créer de nouvelles classes.
  2. Il ne serait pas logique pour la classe d'avoir un constructeur par défaut (Car il nécessite des paramètres/Il n'existe pas de valeurs par défaut qui aurait du sens pour la classe). Dans ce cas, l' = delete est un style de chose, comme @HolyBlackCat dit, mais il n'clarifier votre intention en disant le code client à seulement appeler le constructeur avec paramètres.
  3. Vous ne souhaitez pas que les données non initialisées pour l'ensemble de la classe.

Si la deuxième déclaration n'était pas clair, prenons l'exemple suivant:

class A
{
public:
   //A() = delete; 
   A(int, int) {};
};

Si vous avez essayé d'appeler le constructeur par défaut à droite maintenant, vous obtenez un message d'erreur qui ressemblerait à quelque chose comme (GCC 7.2):

error: no matching function for call to 'A::A()'

Toutefois, si vous décommenté la ligne avec l' = delete, puis vous obtenez le résultat suivant:

erreur: l'utilisation d'un effacement de la fonction 'A::A()'

De ce fait, il explicite clairement que l'on est d'essayer d'utiliser un supprimée constructeur dans le rapport à l'autre erreur, qui est quelque peu incertaine.

5voto

user1997744 Points 271

Plusieurs choix par défaut

Supprimer le constructeur par défaut d'une classe est une bonne idée quand il y a plusieurs choix pour la valeur par défaut ou non initialisée état. Par exemple, supposons que j'ai une classe,

template<typename F>
class Polynomial;

ce qui représente un polynôme sur un champ, F. Dans ce cas, il y a beaucoup de choix pour une valeur par défaut de la fonction polynomiale. L'un pourrait être l'identité pour les polynômes sous plus, c'est à dire zéro, mais nous avons pu également multiplicatif de l'identité, de l'unité. Il dépend de la façon dont l'utilisateur a raison à propos de la classe et comment il est utilisé.


Pas de choix par défaut

L'autre est notamment le cas lorsque, au lieu d'avoir plusieurs états par défaut qui pourrait faire sens, nous n'en avons aucun. Par exemple, supposons que nous avons une classe représentant un collecteur ou d'une surface.

Alors qu'est - Manifold()? C'est un espace vide, avec rien, pas de la surface, pas de notion de distance ou de métrique. Mais alors, il n'est pas logique de penser que c'est un collecteur, mais plutôt peut-être quelque chose de plus général, comme un espace topologique.

Donc, dans ce cas, j'opterais pour supprimer le constructeur par défaut ainsi.

5voto

Pharap Points 804

Parfois, les classes ne sont pas destinés à être instancié.

Un exemple qui n'a pas été mentionné jusqu'à présent sont "trait" classes. Considérons, par exemple, std::char_traits, bien que la norme n'a pas dit que son constructeur par défaut doit être supprimée, son constructeur par défaut est de peu d'utilité, car la classe elle-même est vide, toutes ses fonctions sont statiques et n'ont pas besoin d'être instancié pour utiliser le type d'alias qu'il fournit.

Trait classes sont généralement de ne jamais utilisé à l'appui d'autres classes (généralement d'autres classes de modèle), il peut donc souvent préférable de les supprimer de leur constructeur par défaut - pour renforcer la notion qu'ils sont juste un helper de type et pas vraiment censé être utilisé comme un objet.

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