6 votes

Quand un constructeur c++ n'est pas appelé?

J'ai une situation où aucun constructeur ne semble être appelé:

#include 

using namespace std;

int main ()
{
    class yoyo
    {
        public:
        int i;
        yoyo()
        {
            i = 0;
            cout << "initialisé par défaut à 0" << endl;
        }
        yoyo (int j) : i(j)
        {
            cout << "initialisé à " << j << endl;
        }
    };

    int i;

    yoyo a;
    cout << "Bonjour1, i: " << a.i << endl;

    yoyo b(5);
    cout << "Bonjour2, i: " << b.i << endl;

    yoyo c = b;                                   /* 1 */
    cout << "Bonjour3, i: " << c.i << endl;

    return 0;
}

La sortie est:

initialisé par défaut à 0
Bonjour1, i: 0
initialisé à 5
Bonjour2, i: 5
Bonjour3, i: 5

(Remarque: rien entre Bonjour2 et Bonjour3)

Si je modifie le programme comme suit:

#include 

using namespace std;

int main ()
{
    class yoyo
    {
        public:
        int i;
        yoyo()
        {
            i = 0;
            cout << "initialisé par défaut à 0" << endl;
        }
        yoyo (int j) : i(j)
        {
            cout << "initialisé à " << j << endl;
        }
    };

    int i;

    yoyo a;
    cout << "Bonjour1, i: " << a.i << endl;

    yoyo b(5);
    cout << "Bonjour2, i: " << b.i << endl;

    yoyo c; c = b;                                  /* 1 */
    cout << "Bonjour3, i: " << c.i << endl;

    return 0;
}

(La seule différence réside dans la ligne marquée par /* 1 */)

La sortie est maintenant:

initialisé par défaut à 0
Bonjour1, i: 0
initialisé à 5
Bonjour2, i: 5
initialisé par défaut à 0
Bonjour3, i: 5

Maintenant, il y a un appel au constructeur entre Bonjour2 et Bonjour3. Ma question est, pourquoi n'y a-t-il pas d'appel de constructeur (visible) dans le premier cas?

16voto

Joachim Pileborg Points 121221

Dans le cas de

yoyo c = b;

c'est le constructeur par recopie qui est appelé.

Et dans le cas de

yoyo c; c = b;

c'est l'opérateur d'affectation par recopie qui est appelé.

Si vous n'en fournissez aucun, le compilateur générera pour vous des versions par défaut.


Si vous souhaitez créer votre propre constructeur par recopie, il pourrait ressembler à ceci:

yoyo(const yoyo& other)
    : i(other.i)
    { std::cout << "constructeur par recopie initialisé\n"; }

L'opérateur d'affectation par recopie ressemble à ceci:

yoyo& operator=(const yoyo& other)
    {
        i = other.i;
        return *this;
    }

Les deux sont définis à l'intérieur de la définition de la classe bien sûr.

7voto

taocp Points 14822

Dans le premier cas :

yoyo c = b;   

appelle le constructeur de copie, que le compilateur génère pour vous implicitement dans ce cas.

3voto

0x499602D2 Points 36421
 yoyo c = b; 

Ceci est appelé initialisation par copie; le constructeur par copie généré par le compilateur sera appelé et c sera initialisé avec cette copie. De plus, le constructeur par défaut de c sera appelé.

c = b;

Ici, ce n'est pas une initialisation, c'est une attribution. L'opérateur d'assignation généré par le compilateur sera invoqué sur cette ligne.

1voto

user3133879 Points 11

Dans votre code,

yoyo c=b appellera le constructeur de copie. Si vous voulez voir qu'il est appelé, vous devez le définir explicitement.

ex :

yoyo(const yoyo& obj)
{
   this->i=obj.i;  cout<<"constructeur de copie"<

`dans le deuxième cas, il appellera le constructeur puis l'opérateur d'attribution

yoyo c; //constructeur
c = b;  //opérateur d'attribution pour lequel seule la copie se produit

vous pouvez surcharger l'opérateur d'attribution comme ci-dessous

yoyo& operator=(yoyo& obj)
{
    i = obj.i;
    cout << "opérateur d'attribution" << endl;
}`

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