163 votes

Pourquoi le constructeur par défaut sans paramètre disparaît-il lorsque vous en créez un avec des paramètres

En C#, C++ et Java, lorsque vous créez un constructeur prenant des paramètres, la valeur par défaut sans paramètre on s'en va. J'ai toujours accepté ce fait, mais maintenant, j'ai commencé à me demander pourquoi.

Quelle est la raison de ce comportement? Est-ce juste une "mesure de sécurité/deviner" en disant: "Si vous avez créé un constructeur de votre propre, vous probablement ne voulez pas de cette implicite de traîner"? Ou faut-il une raison technique qui rend impossible pour le compilateur pour ajouter une fois que vous avez créé un constructeur vous-même?

222voto

Dan Puzey Points 20794

Il n'y a pas de raison pour que le compilateur ne pouvais pas ajouter le constructeur si vous avez ajouté votre propre - le compilateur pourrait faire à peu près ce qu'il veut! Cependant, vous devez regarder ce qui est le plus judicieux:

  • Si je n'ai pas défini de tout constructeur, pour un non-statique de la classe, je veux être en mesure d'instancier cette classe. Afin de permettre cela, le compilateur doit ajouter un constructeur sans paramètre, qui n'aura aucun effet, mais pour permettre l'instanciation. Cela signifie que je n'ai pas d'inclure un constructeur vide dans mon code pour le faire fonctionner.
  • Si j'ai défini un constructeur de ma propre, surtout avec les paramètres, puis j'ai plus de chances d'avoir la logique de mon propre qui doit être exécuté sur la création de la classe. Si le compilateur était de créer un vide, constructeur sans paramètre dans ce cas, il serait de permettre à quelqu'un de sauter la logique que j'avais écrit, qui pourrait conduire à mon code de rupture dans tous certain nombre de façons. Si je veux un défaut constructeur vide dans ce cas, j'ai besoin de le dire explicitement.

Donc, dans chaque cas, vous pouvez voir que le comportement de compilateurs gcc fait le plus de sens en termes de préservation de la probable intention de le code.

71voto

Jon Skeet Points 692016

Il n'y a certainement aucune raison technique de la langue a être conçu de cette façon.

Il existe quatre un peu réaliste options que je peux voir:

  1. Pas de constructeurs par défaut à tous les
  2. Le scénario actuel
  3. Toujours fournir un constructeur par défaut par défaut, mais lui permettant d'être explicitement supprimée
  4. Toujours fournir un constructeur par défaut sans lui permettant d'être supprimé

L'Option 1 est assez attrayant, en ce sens que plus je code le moins souvent, j'ai vraiment envie d'un constructeur sans paramètre. Un jour, je devrais compter juste combien de fois j'ai effectivement fin à l'aide d'un constructeur par défaut...

Option 2-je suis très bien avec.

Option 3 va à l'encontre de l'écoulement de Java et en C#, pour le reste de la langue. Il n'y a jamais rien de ce que vous avez explicitement "supprimer", sauf si vous comptez explicitement de rendre les choses plus privées, qu'ils le seraient par défaut en Java.

L'Option 4 est horrible - vous absolument voulez être en mesure de la force de la construction avec certains paramètres. Que serait - new FileStream() même moyenne?

Donc, fondamentalement, si vous accepter la prémisse que la fourniture d'un constructeur par défaut de sens à tous, je crois qu'il fait beaucoup de sens pour le supprimer dès que vous fournissez votre propre constructeur.

20voto

Jon Hanna Points 40291

Edit. En fait, tout ce que je dis dans ma première réponse est valide, c'est la vraie raison.:

Au début il y avait C. C n'est pas orienté objet (vous pouvez prendre une approche OO, mais il ne vous aide pas ou imposer quoi que ce soit).

Puis il y a de C Avec des Classes, qui a été renommé plus tard en C++. C++ est orienté objet, et, par conséquent, encourage l'encapsulation, et de s'assurer d'un objet invariant lors de la construction et du début et de la fin de la méthode, l'objet est dans un état valide.

La chose naturelle à faire, est de faire valoir qu'une classe doit toujours avoir un constructeur pour s'assurer qu'il démarre dans un état valide - si le constructeur n'a rien à faire pour s'en assurer, alors le constructeur vide consignera ce fait.

Mais un but avec le C++ est compatible avec C au point que, autant que possible, valide tous les programmes en C, où valide les programmes C++ (qui n'est plus aussi actif un but, et l'évolution de C distinct de C++ signifie qu'il ne tient plus).

L'une des conséquences de ceci est la duplication de fonctionnalités entre struct et class. L'ancien faire des choses comme en C (tout ce qui est public par défaut) et le dernier à faire les choses bien OO façon (tout ce qui est privé par défaut, développeur activement rend public ce qu'ils veulent publique).

Un autre est que, pour un C struct, ce qui ne pouvait pas avoir un constructeur parce que le C n'a pas de constructeurs, pour être valide en C++, puis il y avait un sens pour ce pour le C++ façon de voir les choses. Et donc, bien que n'ayant pas un constructeur irait à l'encontre de l'OO pratique de la veille activement à un invariant, C++ a pris ce à dire qu'il y avait un défaut constructeur sans paramètre qui a agi comme il avait un corps est vide.

Tous les C structs étaient maintenant valide en C++ structs, (ce qui signifiait qu'ils étaient les mêmes qu'en C++ classes avec tout les membres de l'héritage - public) traité de l'extérieur, comme si elle avait un seul constructeur sans paramètre.

Toutefois, si vous avez mis un constructeur dans un class ou struct, alors que vous faisiez les choses le C++/OO façon plutôt que comme en C, et il n'y avait pas besoin d'un constructeur par défaut.

Depuis, il a servi comme une abréviation, les gens de les utiliser même lorsque la compatibilité n'était pas possible de faire autrement (il a utilisé d'autres fonctionnalités C++ en C).

C'est pourquoi, lorsque Java est venu le long de (basé sur le C++ dans de nombreuses façons) et, plus tard, C# (basé sur le C++ et Java de différentes manières), ils ont gardé cette approche comme quelque chose de codeurs peuvent déjà être utilisé.

Stroustrup écrit à ce sujet dans son Le Langage de Programmation C++ et plus encore, avec plus d'accent sur le "pourquoi" de la langue dans La Conception et l'Évolution de C++.

=== Réponse Originale À Cette Question ===

Disons que ce n'est pas arrivé.

Disons que je ne veux pas d'un constructeur sans paramètre, parce que je ne peux pas mettre ma classe significative de l'état sans que l'un. En effet, c'est quelque chose qui peut se produire avec l' struct en C# (mais si vous ne pouvez pas faire une utilisation judicieuse de tous les zéros et les valeurs null struct en C# vous êtes, au mieux, à l'aide d'un non-public-visible de l'optimisation, et ont un défaut de conception à l'aide de struct).

Pour faire de ma classe en mesure de protéger ses invariants, j'ai besoin d'un spécial removeDefaultConstructor mot-clé. Au moins, j'aurais besoin de créer un privé constructeur sans paramètre pour s'assurer qu'aucun code d'appel des appels par défaut.

Ce qui complique la langue un peu plus. Mieux de ne pas le faire.

Dans tous, il est préférable de ne pas penser à ajouter un constructeur que la suppression du défaut, mieux à penser de ne pas avoir de constructeur tout comme sucre syntaxique pour l'ajout d'un constructeur sans paramètre qui ne fait rien.

13voto

Anders Abel Points 36203

Par défaut, le constructeur sans paramètre est ajouté si vous ne faites rien vous-même pour prendre le contrôle sur la création d’objets. Une fois que vous avez créé un seul constructeur pour prendre le contrôle, le compilateur « recule » et vous permet d’avoir le plein contrôle.

Si il ne serait pas de cette façon, vous auriez besoin d’une manière explicite de désactivation du constructeur par défaut si vous souhaitez uniquement aux objets d’être constructibles par un constructeur avec des paramètres.

3voto

Botz3000 Points 23640

Je pense que la question devrait être dans l'autre sens: Pourquoi n'avez-vous pas besoin de déclarer un constructeur par défaut si vous n'avez pas défini d'autres constructeurs?

Un constructeur est obligatoire pour les non-classes statiques.
Donc je pense que si vous n'avez pas défini de tout les constructeurs, à la génération de constructeur par défaut est seulement une fonction pratique de le compilateur C#, également votre classe ne serait pas valable sans un constructeur. Donc rien de mal avec implicitement la génération d'un constructeur qui ne fait rien. Il est certainement plus propre que d'avoir vide les constructeurs tout autour.

Si vous avez déjà défini un constructeur, votre classe est valide, alors pourquoi le compilateur suppose que vous voulez un constructeur par défaut? Que faire si vous n'en voulez pas? Mettre en œuvre un attribut de dire que le compilateur génère pas de constructeur par défaut? Je ne pense pas que ce serait une bonne idée.

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