C ++ Learning: Polymorphism and Slicing

Consider the following example:

#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(); } 

Output:

 rawr bark rawr bark 

But I thought, of course, the output should be "rawr bark bark . What about badDog?"




Update: you may be interested in another question of mine .

+52
c ++ polymorphism
Dec 09 '10 at 22:19
source share
4 answers

This is a problem called slicing.

Dog() creates a Dog object. If you need to call Dog().makeSound() , it will print a β€œbark” as you expect.

The problem is that you initialize badDog , which is an object of type Animal , with this Dog . Since Animal can only contain Animal , and not anything derived from Animal , it accepts the Animal part of Dog and initializes itself with it.

The type of badDog always Animal ; it can never be anything else.

The only way you can get polymorphic behavior in C ++ is to use pointers (as you demonstrated with the goodDog example) or using links.

A reference (e.g., Animal& ) can refer to an object of any type derived from Animal , and a pointer (e.g., Animal* ) can point to an object of any type derived from Animal . A simple Animal , however, is always Animal , nothing more.

Some languages, such as Java and C #, have reference semantics, where variables (in most cases) are just references to objects, so given Animal rex; rex is actually just a reference to some Animal and rex = new Dog() makes rex reference to a new Dog object.

C ++ does not work like this: variables are not objects in C ++, variables are objects. If you say rex = Dog() in C ++, it copies the new Dog object to rex , and since rex is of type Animal , it is sliced ​​and parts of Animal copied. They are called semantics of values, which are used by default in C ++. If you need reference semantics in C ++, you need to explicitly use references or pointers (none of them match references to C # or Java, but they are more similar).

+72
Dec 09 '10 at 22:24
source share
  Animal badDog = Dog(); ad.makeSound(); 

When you create a Dog instance and assign it by the value of the Animal variable, you are a slice of the object. This basically means that you disconnect all Dog -ness from badDog and go into the base class.

To use polymorphism with base classes, you must use either pointers or references.

+11
Dec 09 '10 at 22:24
source share

I helped you by giving an answer to your thread that was related to this:

C ++ Learning: Link Reversing and Slicing Bypass

I think this will help other people.

0
Jul 20 '19 at 11:31 on
source share

You initialized badDog with the assignment operator. Thus, Dog () was copied as Animal. The result of your program is correct. :)

-one
Dec 09 '10 at
source share



All Articles