Apprendimento del C ++: polimorfismo e affettatura

Considera il seguente esempio:

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

L’output è:

 rawr bark rawr bark 

Ma ho pensato che sicuramente l’output dovrebbe essere “rawr bark bark bark”. Cosa c’è nel baddog?


Aggiornamento: potresti essere interessato ad un’altra mia domanda .

Questo è un problema chiamato “slicing”.

Dog() crea un object Dog . Se si dovesse chiamare Dog().makeSound() , verrà stampato “bark” come previsto.

Il problema è che stai inizializzando il badDog , che è un object di tipo Animal , con questo Dog . Poiché l’ Animal può contenere solo un Animal e non qualcosa derivato da Animal , prende la parte Animal del Dog e si inizializza con quello.

Il tipo di badDog è sempre Animal ; non può mai essere qualcos’altro

L’unico modo per ottenere un comportamento polimorfico in C ++ è l’uso di puntatori (come è stato dimostrato con l’esempio goodDog ) o l’utilizzo di riferimenti.

Un riferimento (ad esempio, Animal& ) può fare riferimento a un object di qualsiasi tipo derivato da Animal e un puntatore (ad esempio, Animal* ) può puntare a un object di qualsiasi tipo derivato da Animal . Un semplice Animal , tuttavia, è sempre un Animal , nient’altro.

Alcuni linguaggi come Java e C # hanno una semantica di riferimento, dove le variabili sono (nella maggior parte dei casi) solo riferimenti agli oggetti, quindi dato un Animal rex; , rex è in realtà solo un riferimento ad alcuni Animal , e rex = new Dog() fa riferimento a un nuovo object Dog .

C ++ non funziona in questo modo: le variabili non si riferiscono agli oggetti in C ++, le variabili sono oggetti. Se si dice rex = Dog() in C ++, copia un nuovo object Dog in rex e poiché rex è in realtà di tipo Animal , viene tagliato e vengono copiate solo le parti di Animal . Questi sono chiamati semantica del valore, che sono predefiniti in C ++. Se si desidera una semantica di riferimento in C ++, è necessario utilizzare esplicitamente riferimenti o riferimenti (nessuno di questi è uguale ai riferimenti in C # o Java, ma sono più simili).

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

Quando istanzia un Dog e lo assegni per valore a una variabile Animal , dividi l’object. Il che significa sostanzialmente che togli tutti i Dog -ness da badDog e badDog entrare nella class base.

Per utilizzare il polimorfismo con le classi di base, è necessario utilizzare i puntatori o i riferimenti.

Hai inizializzato badDog usando l’operatore di assegnazione. Così Dog () è stato copiato come animale. L’output del tuo programma è corretto. 🙂