57 votes

Combien de constructeurs la classe possède-t-elle ?

Je me prépare pour un prochain examen C++ et je suis tombé sur cette question concernant les classes et les constructeurs :

Combien de constructeurs la classe Fraction possède-t-elle ?"

class Fraction {
//...
public:
   Fraction(int numerator = 0, int denominator = 1);
//...
};

Je pensais qu'il n'y en avait qu'un, mais ils ont suggéré qu'il y en avait trois :

Fraction();
Fraction(n);
Fraction(n, d);

Ou en d'autres termes :
Une fonction avec des valeurs par défaut est-elle une fonction surchargée ?

55voto

R Sahu Points 24027

Il n'y a qu'un seul constructeur correspondant à la déclaration affichée, et non trois surcharges.

Les appels

Fraction();
Fraction(n);

sont équivalents :

Fraction(0, 1);
Fraction(n, 1);

Une autre façon de se convaincre qu'il n'y a qu'un seul constructeur correspondant à la déclaration est que vous ne devez définir qu'un seul constructeur, et non trois.

La section de la norme C++11 sur les arguments par défaut contient ceci :

8.3.6 Arguments par défaut

1 Si un clause d'initialisation est spécifié dans un déclaration des paramètres este clause d'initialisation est utilisé comme argument par défaut. Les arguments par défaut seront utilisés dans les appels où les arguments de queue 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 de ces façons :

point(1,2); point(1); point();

Les deux derniers appels sont équivalents à point(1,4) y point(3,4) respectivement. -fin de l'exemple ]

Maintenant, la question principale.

Combien de constructeurs la classe Fraction possède-t-elle ?

Si la personne qui a formulé la question veut inclure le constructeur move et le constructeur copy, qui sont implicitement générés par le compilateur à moins d'être explicitement supprimés, dans l'ensemble des constructeurs, alors la réponse est trois . Dans ce cas, la question est une question piège.

27voto

πάντα ῥεῖ Points 15683

Une fonction avec des valeurs par défaut est-elle une fonction surchargée ?

Non. Les surcharges ressemblent

Fraction();
Fraction(int numerator);
Fraction(int numerator, int denominator);

et ont chacune leur propre implémentation (définition), tandis qu'une fonction avec des paramètres par défaut a une seule implémentation.


Je pensais qu'il n'y en avait qu'un, mais ils ont suggéré qu'il y en avait 3 : ...

"Combien de constructeurs a la classe Fraction ?"

C'est une question piège, conçue pour vous tromper en vous montrant les variantes d'appel disponibles pour une Constructeur unique déclaration.

El définitif La réponse pour l'extrait de code donné est 3 (en mots trois ).

Il y a 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 faites pas de delete ou fournir une 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 cet 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 profondeur pourquoi vous le pensez (comme expliqué ci-dessus).
Dans n'importe quel examen oral, je vous demanderais de justifier pourquoi exactement, ce que je ferais aussi dans un test d'apprentissage.

18voto

TheCppZoo Points 801

La réponse à votre question est relative à ces trois questions de suivi :

  1. Avant C++ 11, C++ 11, ou C++14 et au-delà ?
  2. Les constructeurs définis implicitement comptent-ils ?
  3. Quels sont les membres ? La présence d'un membre non copiable supprimera le constructeur de copie implicite.

La définition explicite est un seul constructeur ; le compilateur insérera un appel à trois arguments, que l'appel fournisse explicitement 0, 1 ou 2 arguments.

Dans la version antérieure à 11, il n'y a pas de constructeurs de mouvements, dans la version 11, il y a deux définitions de constructeurs implicites, Fraction(const Fraction &) noexcept y Fraction(Fraction &&) noexcept Vérifiez l'accessibilité Référence cpp En 14, les règles concernant l'existence d'un constructeur de mouvement implicitement défini ont changé.

La question que vous avez reçue est malheureusement d'apparence innocente mais assez technique ; j'espère que votre classe n'insiste pas pour simplifier à l'extrême le C++, c'est la pire façon de l'apprendre.

5voto

skypjack Points 5516

Vous n'avez qu'une seule déclaration d'un constructeur.
De l'autre côté :

Lorsque deux ou plusieurs déclarations différentes sont spécifiées pour un même nom dans la même portée, on dit que ce nom est surchargé.

Pour cette raison, je n'utiliserais pas le terme surchargé ici.

-4voto

user6473721 Points 1

Ce type de définition de fonction définit une seule fonction mais 2 syntaxes d'appel supplémentaires. La différence subtile devient apparente lorsque l'on prend des pointeurs de fonction ou que l'on fait correspondre un argument de fonction modèle à des fonctions surchargées : dans ce cas, vous n'avez qu'une fonction avec une liste d'arguments complète comme type surchargé disponible.

Le problème est que nous parlons ici d'un constructeur, et un constructeur ne s'engage pas dans le même type de résolution de surcharge qu'une fonction ordinaire et n'est, à toutes fins utiles, pas accessible autrement que syntaxiquement. En particulier, cette définition hace compte séparément comme un constructeur par défaut. Il compte également séparément comme un constructeur de conversion de int et peut être utilisé comme ((Fraction)3).

Donc, à toutes fins pratiques, cela crée trois différents syntaxique dans la catégorie des constructeurs. Et contrairement aux fonctions ordinaires, il n'existe pas de contexte fonctionnel où la résolution de surcharge exposerait la différence entre trois signatures de fonctions réelles et trois conventions d'appel purement syntaxiques.

Ce n'est pas une bonne question pour un test écrit. C'est vraiment quelque chose pour un examen oral car il y a tellement de subtilités impliquées que la différence entre une réponse formellement correcte (s'il y en a une) et une réponse formellement fausse n'est pas susceptible d'être bien corrélée avec les connaissances et les compétences réelles, et le raisonnement derrière toute réponse est plus important que la réponse elle-même.

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