This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
in204:cpp:syntax:class:constructor:spezialized [2019/09/29 13:06] bmonsuez created |
in204:cpp:syntax:class:constructor:spezialized [2022/11/18 10:50] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Les constructeurs spécialisés ====== | ====== Les constructeurs spécialisés ====== | ||
- | Un constructeur de promotion ou de conversion d'une classe ''MyClass'' est : | + | Un constructeur spécialisé d'une classe ''MyClass'' est : |
* un constructeur ''MyClass(ArgumentType1, ArgumentType2)'' qui prend au moins deux paramètres comme argument, | * un constructeur ''MyClass(ArgumentType1, ArgumentType2)'' qui prend au moins deux paramètres comme argument, | ||
- | * le type du paramètre ''ArgumentType'' n'est fait une référence à ''MyClass'', ie. ''ArgumentType'' n'est pas égal à ''const MyClass&''((''MyClass(const MyClass&)'' est appelé [[in204:cpp:syntax:class:constructor:copy|constructeur de recopie]]. | + | ou |
+ | * un constructeur qui prend un paramètre comme argument, qui n'est pas un [[in204:cpp:syntax:class:constructor:copy|constructeur de recopie]] et qui est marqué [[in204:cpp:syntax:class:constructor:conversion|''explicit'']] | ||
<code cpp> | <code cpp> | ||
Line 28: | Line 29: | ||
</code> | </code> | ||
- | Dans la classe ''Complex'', le constructeur ''Complex(double aFloat)'' définit un constructeur de conversion qui prend une valeur ayant pour type ''double'' comme argument. Ce constructeur permet de convertir une valeur flottante en un nombre complexe réel. Il s'agit a priori d'une fonction de conversion, c'est pour cela que ce type d'opérateur porte comme **constructeur de contruction ou de promotion**. | + | Dans la classe ''Complex'', le constructeur ''Complex(double, double)'' définit un **constructeur spécialisé** qui prend deux arguments, la partie entière et la partie imaginaire d'un nombre complexe et crée un objet de type ''Complex'' qui correspond à un objet ayant pour partie réelle et pour partie imaginaire les arguments. |
+ | |||
+ | Il est possible de définir plusieurs constructeurs spécialisés, cependant, il est nécessaire que le nombre d'arguments ou le type d'arguments permettent de différencier les constructeurs spécialisés les uns des autres. | ||
+ | |||
+ | Ainsi pour la définition des nombres complexes, nous pouvons avoir envie de définir deux constructeurs spécialisés : | ||
+ | |||
+ | <code cpp> | ||
+ | Complex(double theReal, double theImaginary): | ||
+ | re(theReal), im(theImaginary) | ||
+ | {} | ||
+ | Complex(double theRho, double thePhi): | ||
+ | re(theRho* cos(thePhi)), im(theRho* sin(thePhi)) | ||
+ | {} | ||
+ | </code> | ||
+ | |||
+ | Cependant dans ce cas, les deux constructeurs ont le même nombre d'arguments et les arguments ont le même type. Comment distinguer entre les signatures des deux constructeurs ? | ||
+ | <code cpp> | ||
+ | Complex(double, double) // theReal, theImaginary | ||
+ | Complex(double, double) // theRho, thePhy | ||
+ | </code> | ||
+ | |||
+ | De fait, il n'y a pas de moyens simples. Il existe alors deux méthodes pour pouvoir lever l'ambiguité. | ||
+ | |||
+ | Nous pouvons créer des méthodes statiques de créations des objets : | ||
+ | |||
+ | <code cpp> | ||
+ | class Complex | ||
+ | { | ||
+ | private: | ||
+ | double re; | ||
+ | double im; | ||
+ | |||
+ | public: | ||
+ | Complex(): re(0.0), im(0.0) // Constructeur par défaut. | ||
+ | {} | ||
+ | Complex(const Complex& theSource): // Constructeur de recopie | ||
+ | re(theSource.re), im(theSource.im) | ||
+ | {} | ||
+ | Complex(double aFloat): // Conversion | ||
+ | re(aFloat), im(0.0) | ||
+ | {} | ||
+ | Complex(double theReal, double theImaginary) | ||
+ | re(theReal), im(theImaginary) // Constructeur spécialisé | ||
+ | {} | ||
+ | |||
+ | static Complex from_polar(double theRho, double thePhi) | ||
+ | { | ||
+ | return Complex( | ||
+ | theRho* cos(thePhi), | ||
+ | theRho* sin(thePhi)); | ||
+ | } | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Pour créer un nombre complexe à partir de ses parties réelles et imaginaires, resp. ses coordonnées polaires, il faudra soit appeler son constructeur, soit appeler la méthode statique : | ||
+ | <code cpp> | ||
+ | Complex complexA(1.0, 2.0); | ||
+ | Complex complexB = Complex::from_polar(1.0, 0,52); | ||
+ | </code> | ||
+ | |||
+ | ou au contraire nous pouvons ajouter des paramètres pour lever l'ambiguité au moment de la compilation. | ||
+ | |||
+ | <code cpp> | ||
+ | class Complex | ||
+ | { | ||
+ | public: | ||
+ | |||
+ | class Polar {}; // Classe vide ne servant qu'à définir un | ||
+ | // type additionnel pour identifier | ||
+ | // une conversion polaire vers complexe. | ||
+ | private: | ||
+ | double re; | ||
+ | double im; | ||
+ | |||
+ | public: | ||
+ | Complex(): re(0.0), im(0.0) // Constructeur par défaut. | ||
+ | {} | ||
+ | Complex(const Complex& theSource): // Constructeur de recopie | ||
+ | re(theSource.re), im(theSource.im) | ||
+ | {} | ||
+ | Complex(double aFloat): // Conversion | ||
+ | re(aFloat), im(0.0) | ||
+ | {} | ||
+ | Complex(double theReal, double theImaginary) | ||
+ | re(theReal), im(theImaginary) // Constructeur spécialisé | ||
+ | {} | ||
+ | Complex(Polar, double theRho, double thePhi) | ||
+ | re(theRho* cos(thePhi)), im(theRho* sin(thePhi)) | ||
+ | {} | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Désormais, les deux constructeurs ont bien une signature de type différente : | ||
+ | |||
+ | <code cpp> | ||
+ | Complex(double, double) | ||
+ | Complex(Polar, double, double) | ||
+ | </code> | ||
+ | |||
+ | Pour créer un nombre complexe à partir de ses parties réelles et imaginaires, resp. ses coordonnées polaires, il suffira d'écrire : | ||
+ | <code cpp> | ||
+ | Complex complexA(1.0, 2.0); | ||
+ | Complex complexB(Polar(), 1.0, 0,52); | ||
+ | </code> | ||