Veuillez me dire pourquoi le constructeur ne renvoie aucune valeur. Je veux une raison technique parfaite pour expliquer à mes étudiants pourquoi le constructeur n'a pas de type de retour.
Pouvons-nous supposer que vous décrivez .NET ?
Veuillez me dire pourquoi le constructeur ne renvoie aucune valeur. Je veux une raison technique parfaite pour expliquer à mes étudiants pourquoi le constructeur n'a pas de type de retour.
Ce qui se passe en fait avec le constructeur, c'est que le runtime utilise les données de type générées par le compilateur pour déterminer l'espace nécessaire pour stocker une instance d'objet en mémoire, que ce soit sur la pile ou sur le tas.
Cet espace comprend toutes les variables des membres et la vtbl. Une fois cet espace alloué, le constructeur est appelé en tant que partie interne du processus d'instanciation et d'initialisation pour initialiser le contenu des champs.
Ensuite, lorsque le constructeur se termine, le runtime renvoie l'instance nouvellement créée. La raison pour laquelle le constructeur ne renvoie pas de valeur est qu'il n'est pas appelé directement par votre code, mais par le code d'allocation de la mémoire et d'initialisation de l'objet dans le runtime.
Sa valeur de retour (si elle en a une lorsqu'elle est compilée en code machine) est opaque pour l'utilisateur - vous ne pouvez donc pas la spécifier.
Bien que ce soit techniquement détaillé et correct, un simple "il n'a pas été conçu pour le faire" suffirait, à mon avis. Il ne serait certainement pas impossible de concevoir le runtime pour qu'il renvoie la valeur de retour du constructeur au lieu de l'instance nouvellement créée. Cela n'a tout simplement pas beaucoup de sens et n'a donc pas été conçu pour le faire :)
Je ne suis pas certain de l'existence de .Net - ce qui précède est ma compréhension de l'approche adoptée par C++. Je suis sûr que .Net est très similaire, sauf que les métadonnées générées par le compilateur englobent BEAUCOUP plus que la quantité d'espace requise pour l'instancier (et c++ stocke également quelques métadonnées sur le type, mais rien à l'échelle supportée par .Net).
Alors pourquoi cette méthode ne serait-elle pas autorisée à retourner null
? Je ne suis pas convaincu. Pas du tout.
Cela rend l'utilisation du constructeur beaucoup plus facile si vous savez que les seuls états finaux possibles sont "vous avez une instance Something" ou "une exception est levée". (Nous avons essayé de faire en sorte que l'appelant vérifie chaque valeur de retour en C.) Y a-t-il un avantage à avoir deux mécanismes orthogonaux de rapport d'erreur que l'appelant doit vérifier à chaque fois, ou proposez-vous de supprimer également les exceptions ?
(J'ai un parti pris pour le C++, donc concernant les autres langages, prenez cela avec un grain de sel).
Réponse courte : Vous ne voulez pas avoir à vérifier explicitement le succès de chaque construction d'objet dans votre code.
Réponse un peu plus longue : En C++, les constructeurs sont appelés pour les objets alloués dynamiquement ainsi que pour les objets alloués globalement et automatiquement. Dans ce code
void f()
{
std::string s;
}
il n'y a aucun moyen pour le constructeur de s
( std::string::string()
) pour retourner une valeur quelconque. Soit il réussit - nous pouvons alors utiliser l'objet, soit il lève une exception - nous n'aurons jamais la chance d'essayer de l'utiliser.
IMO, c'est comme ça que ça devrait être.
Comment un constructeur est-il censé renvoyer une valeur de retour ? Le site new
renvoie l'instance nouvellement créée. Vous n'appelez pas un ctor, new
le fait.
MyClass instance = new MyClass();
Si le ctor devait retourner une valeur, comme ceci :
public int MyClass()
{
return 42;
}
Où recevriez-vous l'entier ?
"Comment un constructeur est censé retourner une valeur de retour ?" Il pourrait retourner this
. L'échec de la construction serait indiqué par le retour null
.
Mais "ceci" doit déjà exister lorsque le constructeur commence à fonctionner. Si votre construction "échoue", le "ceci" est déjà alloué, et alors que se passe-t-il ? Vous avez un objet partiellement construit ? Le destructeur doit-il être appelé ou non ? En C++, si vous lancez le constructeur, vous êtes censé sauvegarder suffisamment d'état dans l'objet zombie pour qu'il puisse nettoyer après lui-même ; sans objet, comment peut-il le faire ? Ou bien avez-vous maintenant 2 mécanismes d'erreur complètement indépendants pour les constructeurs ?
Lorsque vous appelez un constructeur, la valeur de retour est le nouvel objet :
Point pt = new Point(1,2);
Mais dans le constructeur lui-même, vous ne créez et ne retournez pas réellement l'objet ; il a été créé avant que votre code ne commence, vous ne faites que définir les valeurs initiales.
Point::Point(int x, int y) {
this->x = x;
this->y = y;
}
L'absence de type de retour reflète le fait que les constructeurs sont utilisés différemment des autres fonctions. Un type de retour de null
bien que techniquement exact, ne reflète pas bien le fait que le code soit utilisé comme s'il retournait un objet. Cependant, tout autre type de retour indiquerait que votre code est censé return
quelque chose à la fin, ce qui est également incorrect.
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.
9 votes
De quelle langue s'agit-il ?
6 votes
Parce qu'il renvoie une instance de la classe. S'il renvoie un type de données, comment allez-vous créer une nouvelle instance ?
0 votes
@Karan Exactement. Les constructeurs renvoient une instance d'une classe, ils ne peuvent donc pas avoir d'autres valeurs de retour.