61 votes

L'apprentissage de C++: polymorphisme et de tranchage

Considérons l'exemple suivant:

#include <iostream>
using namespace std;

class Animal
{
public:
    virtual void makeSound() {cout << "rawr" << endl;}
};

class Dog : public Animal
{
public:
    virtual void makeSound() {cout << "bark" << endl;}
};

int main()
{
    Animal animal;
    animal.makeSound();

    Dog dog;
    dog.makeSound();

    Animal badDog = Dog();
    badDog.makeSound();

    Animal* goodDog = new Dog();
    goodDog->makeSound();
}

La sortie est:

rawr
bark
rawr
bark

Mais j'ai pensé que, sans aucun doute, la sortie doit être "rawr écorce écorce écorce". C'est quoi l'badDog?


Mise à jour: Vous pouvez être intéressé par une autre question de la mienne.

82voto

James McNellis Points 193607

C'est un problème appelé "le découpage."

Dog() crée un Dog objet. Si vous vous appelez Dog().makeSound(), il affiche "écorce" comme vous l'attendez.

Le problème, c'est que vous êtes de l'initialisation de l' badDog, ce qui est un objet de type Animal, avec cette Dog. Depuis l' Animal ne peut contenir qu'un Animal et pas quelque chose dérivée d' Animal, il faut l' Animal de la partie de l' Dog et initialise avec qui.

Le type d' badDog toujours Animal; il ne peut jamais être autre chose.

La seule façon vous pouvez obtenir le comportement polymorphique de C++ à l'aide de pointeurs (comme vous l'avez démontré votre goodDog exemple) ou à l'aide de références.

Une référence (par exemple, Animal&) peut se référer à un objet de type dérivé de Animal et un pointeur (par exemple, Animal*) peut pointer vers un objet de type dérivé de Animal. Une plaine Animal, cependant, est toujours un Animal, rien d'autre.

Certains langages, comme Java et C# référence sémantique, où les variables sont (dans la plupart des cas), juste des références à des objets, donc vu un Animal rex;, rex est vraiment juste une référence à quelques - Animal, et rex = new Dog() fait rex se référer à un nouveau Dog objet.

C++ ne fonctionne pas de cette façon: les variables de ne pas faire référence à des objets en C++, les variables sont des objets. Si vous dites rex = Dog() en C++, il copie un nouveau Dog objet en rex, et depuis rex est en fait de type Animal, il obtient en tranches et juste l' Animal des pièces sont copiées. Ceux-ci sont appelés valeur sémantique, qui sont par défaut en C++. Si vous voulez de référence de la sémantique dans le C++, vous devez utiliser explicitement des références ou des pointeurs (aucune de ces sont les mêmes que les références en C# ou Java, mais ils sont de plus en plus semblables).

11voto

John Dibling Points 56814
 Animal badDog = Dog();
    ad.makeSound();

Lorsque vous instanciez un Dog et l'assigner par-valeur à un Animal variable, vous tranche de l'objet. Ce qui signifie essentiellement que vous dépouiller de tous les Dog-ness de badDog et le faire pour la classe de base.

Afin d'utiliser le polymorphisme avec les classes de base, vous devez utiliser des pointeurs ou des références.

-1voto

Android Eve Points 7604

Vous avez initialisé badDog à l'aide de l'opérateur d'affectation. Donc Chien() a été copié de l'Animal. La sortie de votre programme est correct. :)

-4voto

Crazy Eddie Points 23778

Google "découpage"; vous le faites.

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