5 votes

Comportement de la référence d'objet C++

Considérons le segment de code suivant :

class Window // Base class for C++ virtual function example
     {
       public:
          virtual void Create() // virtual function for C++ virtual function example
          {
               cout <<"Base class Window"<<endl;
          }
     };

     class CommandButton : public Window
     {
       public:
          void Create()
          {
              cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
          }
     };

     int main()
     {
        Window *button = new   CommandButton;
        Window& aRef = *button;
        aRef.Create(); // Output: Derived class Command Button - Overridden C++ virtual function
        Window bRef=*button;
        bRef.Create(); // Output: Base class Window

        return 0;
     }

Les deux sites aRef y bRef être affecté *bouton mais pourquoi les deux sorties sont-elles différentes ? Quelle est la différence entre l'affectation à un type de référence et à un type sans référence ?

10voto

Loki Astari Points 116129

Vous avez rencontré le problème du découpage en tranches.

Window bRef   =*button;

Ici, bRef n'est pas une référence mais un objet. Lorsque vous attribuez un type dérivé à bRef, vous supprimez la partie dérivée, ce qui ne vous laisse qu'un objet Window construit à partir d'un CommandButton.

Ce qui se passe, c'est que bRef est créé dans l'instruction ci-dessus en utilisant le constructeur de copie généré par le compilateur pour la classe Window. Tout ce que fait ce constructeur est de copier les éléments membres de la RHS vers l'objet nouvellement construit. Comme la classe ne contient aucun membre, rien ne se passe.

Remarque : une classe comportant des membres virtuels doit également avoir un destructeur virtuel.

7voto

icecrime Points 23650
  • aRef a Window statique type mais CommandButton dynamique type
  • bRef est simplement un objet de type Window ( le site CommandButton "partie a été perdue dans la copie )

C'est ce qu'on appelle communément découpage d'objets et elle est généralement évitée en rendant les classes de base soit abstraites (en fournissant une fonction virtuelle pure) soit non copiables (par exemple en utilisant boost::noncopyable ), car l'une ou l'autre des solutions ferait échouer la compilation du code à la ligne Window& aRef = *button; .


Maintenant, pourquoi bRef.Create() appelez Window::Create ? Eh bien, il n'y a rien de plus qu'un Window en bRef donc il n'y a pas vraiment d'alternative. Cela revient essentiellement à déclarer un Window et en appelant Create sur elle : le fait que bRef a été copié à partir d'un CommandButton n'est pas pertinente car l'instance CommandButton partie a été perdue dans la copie.

Je vais essayer de rendre cela plus clair en citant la norme (10.3/6) :

[Note : l'interprétation de l'appel d'une fonction virtuelle dépend de la type de l'objet pour lequel elle est appelé ( le type dynamique ), tandis que les l'interprétation d'un appel d'une fonction membre non virtuelle dépend dépend uniquement du type du pointeur ou de la désignant cet objet ( le site type statique ) (5.2.2). ]

Ce n'est que par le biais d'un pointeur ou d'une référence indirecte que le type statique d'un objet peut différer de son type dynamique.

2voto

Prasoon Saurav Points 47488
Window bRef=*button;
bRef.Create(); // Output: Base class Window

Le type statique ainsi que le type dynamique de bRef es Window seulement. Le mécanisme virtuel ne fonctionne qu'avec des références et des pointeurs. bRef est un objet et non une référence ou un pointeur.

1voto

Nawaz Points 148870
 Window bRef=*button;
 bRef.Create(); // Output: Base class Window

Aquí bRef n'est pas la référence à button (vous venez de le nommer ainsi). bRef ne récupère que le sous-objet de base qui est Window .

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