====== Les constructeurs spécialisés ======
Un constructeur spécialisé d'une classe ''MyClass'' est :
* un constructeur ''MyClass(ArgumentType1, ArgumentType2)'' qui prend au moins deux paramètres comme argument,
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'']]
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é
{}
};
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 :
Complex(double theReal, double theImaginary):
re(theReal), im(theImaginary)
{}
Complex(double theRho, double thePhi):
re(theRho* cos(thePhi)), im(theRho* sin(thePhi))
{}
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 ?
Complex(double, double) // theReal, theImaginary
Complex(double, double) // theRho, thePhy
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 :
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));
}
};
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 :
Complex complexA(1.0, 2.0);
Complex complexB = Complex::from_polar(1.0, 0,52);
ou au contraire nous pouvons ajouter des paramètres pour lever l'ambiguité au moment de la compilation.
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))
{}
};
Désormais, les deux constructeurs ont bien une signature de type différente :
Complex(double, double)
Complex(Polar, double, double)
Pour créer un nombre complexe à partir de ses parties réelles et imaginaires, resp. ses coordonnées polaires, il suffira d'écrire :
Complex complexA(1.0, 2.0);
Complex complexB(Polar(), 1.0, 0,52);