Polymorphism and Slicing in C : Decoding the Confusion
In C , polymorphism allows objects derived from a base class to exhibit different behaviors. However, a common pitfall, known as "slicing," can lead to unexpected results.
Question:
Consider the following code snippet:
class Animal { virtual void makeSound() { cout << "rawr" << endl; } }; class Dog : public Animal { 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(); }
The output is:
rawr bark rawr bark
Why does the output for badDog not print "bark"?
Answer:
This is an example of slicing. When you pass a Dog object to the Animal constructor (like in badDog = Dog()), the Animal part of the Dog is copied into badDog. However, since badDog is of type Animal, it can only access the Animal methods, which default to printing "rawr."
To achieve polymorphism, you must use pointers or references to point to the derived class object. In this case, goodDog is a pointer to a Dog object, so it can access the Dog methods and print "bark."
Implications:
Slicing can lead to unexpected behaviors and is generally discouraged. Using pointers or references ensures proper polymorphic behavior.
Additionally, remember that C uses value semantics by default, meaning that variables contain the actual objects. This differs from reference semantics in languages like Java and C#, where variables hold references to objects.
The above is the detailed content of Why Does Slicing Occur in C Polymorphism, and How Can It Be Avoided?. For more information, please follow other related articles on the PHP Chinese website!