Aprendizaje de C ++: polymorphism y corte

Considere el siguiente ejemplo:

#include  using namespace std; class Animal { public: virtual void makeSound() {cout << "rawr" << endl;} }; class Dog : public Animal { public: virtual void makeSound() {cout << "bark" <makeSound(); } 

El resultado es:

 rawr bark rawr bark 

Pero pensé que seguramente la salida debería ser “rawr ladrido ladrido de corteza”. ¿Qué pasa con el badDog?


Actualización: Puede que le interese otra pregunta mía .

Este es un problema llamado “rebanar”.

Dog() crea un objeto Dog . Si llamaras a Dog().makeSound() , imprimiría “ladrar” como esperabas.

El problema es que estás inicializando el badDog , que es un objeto de tipo Animal , con este Dog . Como el Animal solo puede contener un Animal y nada derivado de Animal , toma la parte Animal del Dog y se inicializa con eso.

El tipo de badDog es siempre Animal ; nunca puede ser otra cosa.

La única forma en que puede obtener el comportamiento polimórfico en C ++ es usando punteros (como lo ha demostrado con su ejemplo goodDog ) o usando referencias.

Una referencia (por ejemplo, Animal& ) puede referirse a un objeto de cualquier tipo derivado de Animal y un puntero (por ejemplo, Animal* ) puede señalar a un objeto de cualquier tipo derivado de Animal . Un Animal simple, sin embargo, siempre es un Animal , nada más.

Algunos lenguajes como Java y C # tienen semántica de referencia, donde las variables son (en la mayoría de los casos) solo referencias a objetos, por lo que se les otorga un Animal rex; , rex es realmente solo una referencia a un Animal , y rex = new Dog() hace que rex refiera a un nuevo objeto Dog .

C ++ no funciona de esa manera: las variables no se refieren a objetos en C ++, las variables son objetos. Si dices rex = Dog() en C ++, copia un nuevo objeto Dog en rex , y como rex es en realidad de tipo Animal , se corta y solo se copian las partes de Animal . Estos se denominan semántica de valores, que son los predeterminados en C ++. Si desea semántica de referencia en C ++, necesita usar referencias o punteros explícitamente (ninguno de estos es lo mismo que las referencias en C # o Java, pero son más similares).

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

Cuando instancia un Dog y lo asigna por valor a una variable Animal , corta el objeto. Lo que básicamente significa que te badDog todo el badDog de badDog y lo badDog a la clase base.

Para utilizar el polymorphism con las clases base, debe usar punteros o referencias.

Inicializó badDog usando el operador de asignación. Por lo tanto, Dog () se copió como Animal. La salida de tu progtwig es correcta. 🙂