Je veux dire, il s'agit de choisir des mots plus que toute différence entre la fonction et l'appel du constructeur. La chose qui est nommée "constructeur d'un objet" peut également être nommée "fonction avec nom object
type de retour object
".
On pourrait affirmer que c ++ n'autorise pas à avoir la même fonction et le même nom de type; Cependant, il y a de la solution de contournement pour le faire. C++ a sucre syntaxique spécial (qui est nommé constructeur) avec lequel vous pouvez créer une fonction avec nom object
type de retour object
. Je pense donc qu'un constructeur peut être vu et utilisé comme une fonction de permanence libre.
Y a-t-il des différences sémantiques importantes que je manque ici?
Non, un constructeur de object
est très différent d'une fonction appelée object
et retourner object
. Un constructeur n'a pas de nom, mais c'est largement une technicité. Les différences les plus importantes sont qu'un constructeur n'a pas de type de retour et qu'il ne peut pas être appelé directement.
Un constructeur ne renvoie rien car il est donné un bloc de mémoire et fonctionne sur cette mémoire in-place. Cela pourrait aider si vous oubliez le nom "constructeur" pour un moment et pensez à C'est comme initialiseur à la place. Le but du constructeur est non de construire un objet "hors de l'air mince". Son objectif est d'initialiser un objet à l'endroit précis de la mémoire où il doit être.
Si un constructeur devait renvoyer un objet, cet objet renvoyé (la valeur de retour) devrait vivre quelque part (probablement sur la pile) et là, il aurait besoin d'être initialisé d'une manière ou d'une autre - nous 'Re courir dans une boucle ici.
Cela va de pair avec le fait qu'un constructeur ne puisse jamais être appelé directement. Si vous avez une classe object
et utilisez une expression object()
quelque part, il n'a pas la sémantique de "appeler le constructeur de object
". Il a la sémantique de "créer un objet temporaire de type object
". Le compilateur traduit cela en allouant un endroit pour le temporaire de vivre (probablement/généralement sur la pile) et appeler le constructeur à construire (= initialiser) un objet à cet endroit.
Le même principe s'applique lors de l'utilisation new object()
. C'est une nouvelle expression, qui fait deux choses:
operator new
(Qui renvoie un void*
) Pour allouer la mémoire brute pour l'objet.Penser à un constructeur de object
en tant que fonction comme celle-ci:
static object object();
est faux. Si quelque chose, la façon dont un constructeur fonctionne est plus proche de ceci:
static void object(object &place_to_work_in);
À l'exception que vous pouvez jamais Appelez-le directement. C'est TOUJOURS Appelé uniquement lorsque spécifié par une construction de langue différente. Même le placement neuf (également appelé "appeler un constructeur ici" astuce), new (&place_for_object) object()
, n'appelle pas le constructeur directement. Il se traduit par un appel à la forme de placement-nouvelle de operator new
Qui renvoie son argument, suivi d'un appel au constructeur (comme toute autre nouvelle expression).
Votre tentative de reformulation est incorrecte.
Bien qu'un constructeur ressemble à une fonction de membre avec un nom identique au nom de la classe, le fait est qu'un constructeur n'a pas vraiment de nom du tout. Ceci est explicitement indiqué dans la norme C++ (section [Class.ctor]/1):
Les constructeurs n'ont pas de noms.
En ce qui concerne: "Je pense qu'un constructeur peut être vu et utilisé comme une fonction de perfection libre" va ... Eh bien, je ne suis pas tout à fait sûr de ce que tu veux dire. Une fonction libre ne peut certainement pas être un constructeur - un constructeur doit être membre d'une classe. Dans le même temps, vous pouvez certainement définir une fonction libre qui crée un objet et renvoie une instance de cet objet. Cette fonction gratuite peut même (sorte de) avoir le même nom que le type d'objet qu'il crée, si vous voulez beaucoup assez. Par exemple, vous pouvez définir la classe à l'intérieur d'un espace de noms, puis définissez une fonction à l'extérieur de l'espace de noms:
namespace foo {
class bar {};
}
foo::bar bar() { return foo::bar(); }
Ce n'est pas vraiment Le même nom (la fonction est juste bar
_ et la classe est foo::bar
), Mais en fonction de votre point de vue, vous pouvez trier eux de cette façon quand même.
Une telle fonction libre n'aurait cependant pas les autres caractéristiques essentielles d'un constructeur. L'invocation du constructeur peut être complètement implicite. Par exemple, si j'ai une classe comme:
class foo {
public:
foo (int) {}
foo operator+(foo const &other) {}
};
... alors le code comme:
foo f(1);
foo h(0);
h = f + 1;
... peut créer un objet FOO temporaire à partir du 1
afin qu'il puisse passer cet objet FOO à foo::operator+
. Cela ne se produira tout simplement pas avec une fonction libre, même si cette fonction libre était définie pour prendre le bon type de paramètre et renvoyer le type de résultat requis. Pour une telle conversion implicite, un constructeur est requis.