Je me prépare pour un prochain examen C++ et suis tombé sur cette question concernant les classes et les constructeurs:
Combien de constructeurs possède la classe Fraction? "
class Fraction { //... public: Fraction(int numerator = 0, int denominator = 1); //... };
Je pensais que ce n'était qu'un, mais ils ont suggéré qu'il y en avait trois:
Fraction();
Fraction(n);
Fraction(n, d);
Ou en d'autres termes:
ne fonction avec des valeurs par défaut est-elle une fonction surchargée?
Il n'y a qu'un seul constructeur correspondant à la déclaration publiée, pas trois surcharges.
Les appels
Fraction();
Fraction(n);
sont équivalents à:
Fraction(0, 1);
Fraction(n, 1);
Une autre façon de vous convaincre qu'il n'y a qu'un seul constructeur correspondant à la déclaration est que vous n'avez besoin de définir qu'un seul constructeur, pas trois.
La section de la norme C++ 11 sur les arguments par défaut a ceci:
8.3.6 Arguments par défaut
1 Si une clause d'initialisation est spécifiée dans une déclaration de paramètre , ceci la clause d'initialisation est utilisée comme argument par défaut. Les arguments par défaut seront utilisés dans les appels où les arguments de fin sont manquants.
2 [ Exemple: la déclaration
void point(int = 3, int = 4);
déclare une fonction qui peut être appelée avec zéro, un ou deux arguments de\type
int
. Il peut être appelé de l'une des manières suivantes:point(1,2); point(1); point();
Les deux derniers appels sont équivalents à
point(1,4)
etpoint(3,4)
, respectivement. - exemple de fin ]
Maintenant, la question principale.
Combien de constructeurs possède la classe Fraction?
Si la personne qui a formulé la question souhaite inclure le constructeur de déplacement et le constructeur de copie, qui sont implicitement générés par le compilateur, sauf suppression explicite, dans l'ensemble des constructeurs, alors la réponse est trois. Dans ce cas, la question est une question piège.
ne fonction avec des valeurs par défaut est-elle une fonction surchargée?
Les surcharges ressemblent
Fraction();
Fraction(int numerator);
Fraction(int numerator, int denominator);
et ont chacun leur propre implémentation (définition), tandis qu'une fonction avec des paramètres par défaut a une seule implémentation.
Je pensais que ce n'était qu'un, mais ils ont suggéré qu'il y en avait 3: ...
"Combien de constructeurs possède la classe Fraction?"
La réponse définitive pour l'extrait de code donné est (en mots trois).
Il existe un constructeur spécialisé (qui sert trois variantes d'appel), et le compilateur génère automatiquement un constructeur de copie et de déplacement si vous ne les delete
, ou ne fournissez pas d'implémentation personnalisée:
Fraction(int numerator = 0, int denominator = 1); // (1)
// Redundant, just for demonstration:
Fraction(const Fraction& rhs) = default; // (2)
Fraction(Fraction&& rhs) = default; // (3)
Donc, pour un tel examen, si vous répondez
La classe a un constructeur
C'est faux de toute façon. Si vous répondez
La classe a trois constructeurs (comme vous l'avez écrit, c'est la réponse acceptée)
vous devrez expliquer en détail pourquoi vous pensez que oui (comme expliqué ci-dessus).
Dans tout examen oral, je vous demanderais de sauvegarder pourquoi exactement, donc je le ferais dans un test d'apprenti.
La réponse à votre question est relative à ces trois questions de suivi:
La définition explicite n'est qu'un constructeur; le compilateur insère un appel à trois arguments, que l'appel fournisse explicitement 0, 1 ou 2 arguments.
Dans pré-'11, il n'y a pas de constructeurs de mouvement, dans '11, il y a deux définitions implicites de constructeurs, Fraction(const Fraction &) noexcept
et Fraction(Fraction &&) noexcept
, vérifiez l'accessible cppreference , in '14 les règles du moment où il y a un changement de constructeur de mouvement défini implicitement.
La question que vous vous posez est malheureusement innocente mais assez technique; J'espère que votre classe n'insiste pas sur une simplification excessive du C++, c'est la pire façon de l'apprendre.
Vous n'avez qu'une seule déclaration d'un constructeur.
D'un autre côté:
Lorsque deux ou plusieurs déclarations différentes sont spécifiées pour un seul nom dans la même étendue, ce nom est dit surchargé
Pour cette raison, je n'utiliserais pas le terme surchargé ici.