Éditer. En fait, bien que ce que je dis dans ma première réponse soit valable, c'est la vraie raison:
Au début, il y avait C. C n'est pas orienté objet (vous pouvez adopter une approche OO, mais cela ne vous aide pas ou n'applique rien).
Ensuite, il y a eu C With Classes, qui a ensuite été renommé C ++. Le C ++ est orienté objet, et encourage donc l'encapsulation, et garantit l'invariant d'un objet - lors de la construction et au début et à la fin de toute méthode, l'objet est dans un état valide.
La chose naturelle à faire avec cela, est de faire en sorte qu'une classe doit toujours avoir un constructeur pour s'assurer qu'elle démarre dans un état valide - si le constructeur n'a rien à faire pour garantir cela, alors le constructeur vide documentera ce fait .
Mais un objectif avec C ++ était d'être compatible avec C au point que, dans la mesure du possible, tous les programmes C valides étaient également des programmes C ++ valides (ce n'est plus un objectif aussi actif, et l'évolution du C séparée vers C ++ signifie qu'il ne tient plus) ).
Un effet de ceci était la duplication des fonctionnalités entre struct
et class
. Le premier fait les choses à la manière C (tout est public par défaut) et le second fait les choses d'une bonne manière OO (tout est privé par défaut, le développeur rend activement public ce qu'il veut).
Un autre est que pour qu'un C struct
, qui ne pouvait pas avoir de constructeur parce que C n'a pas de constructeurs, soit valide en C ++, alors il devait y avoir une signification pour cela à la manière C ++ de le voir. Et donc, bien que ne pas avoir de constructeur irait à l'encontre de la pratique OO d'assurer activement un invariant, C ++ a pris cela pour signifier qu'il y avait un constructeur sans paramètre par défaut qui agissait comme s'il avait un corps vide.
Tous les C structs
étaient désormais des C ++ valides structs
, (ce qui signifiait qu'ils étaient identiques à C ++ classes
avec tout - membres et héritage - public) traités de l'extérieur comme s'il avait un seul constructeur sans paramètre.
Si toutefois vous avez mis un constructeur dans un class
ou struct
, alors vous faisiez les choses de la manière C ++ / OO plutôt que de la manière C, et il n'y avait pas besoin d'un constructeur par défaut.
Puisqu'il servait de raccourci, les gens continuaient à l'utiliser même lorsque la compatibilité n'était pas possible autrement (il utilisait d'autres fonctionnalités C ++ pas en C).
Par conséquent, lorsque Java est arrivé (basé sur C ++ à bien des égards) et plus tard C # (basé sur C ++ et Java de différentes manières), ils ont conservé cette approche car les codeurs étaient peut-être déjà habitués.
Stroustrup écrit à ce sujet dans son The C ++ Programming Language et plus encore, avec plus d'attention sur les «pourquoi» du langage dans The Design and Evolution of C ++ .
=== Réponse originale ===
Disons que cela ne s'est pas produit.
Disons que je ne veux pas d'un constructeur sans paramètre, car je ne peux pas mettre ma classe dans un état significatif sans un. En effet, c'est quelque chose qui peut arriver avec struct
en C # (mais si vous ne pouvez pas utiliser de manière significative un tous les zéros et les nuls struct
en C #, vous utilisez au mieux une optimisation non visible publiquement, et sinon défaut de conception lors de l'utilisation struct
).
Pour rendre ma classe capable de protéger ses invariants, j'ai besoin d'un removeDefaultConstructor
mot-clé spécial . À tout le moins, je devrais créer un constructeur privé sans paramètre pour m'assurer qu'aucun code d'appel n'appelle la valeur par défaut.
Ce qui complique encore la langue. Mieux vaut ne pas le faire.
Dans l'ensemble, il vaut mieux ne pas penser à ajouter un constructeur comme supprimant la valeur par défaut, mieux vaut penser à ne pas avoir de constructeur du tout comme du sucre syntaxique pour ajouter un constructeur sans paramètre qui ne fait rien.