学习C ++:多态性和切片

考虑以下示例:


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

}

输出为:


rawr

bark

rawr

bark

但是我认为输出肯定应该是“ raw kark bark bark”。badDog怎么了?


更新:您可能对我的另一个问题感兴趣。


www说
浏览 437回答 3
3回答

一只斗牛犬

这是一个称为“切片”的问题。Dog()创建一个Dog对象。如果您要致电Dog().makeSound(),它将按您期望的那样打印“树皮”。问题是,你是初始化badDog,这是类型的对象Animal,与此Dog。由于Animal只能包含Animal和,而不能包含从派生的任何内容Animal,因此它会占用的Animal一部分Dog并以此进行初始化。的类型badDog总是Animal;&nbsp;它永远不可能是别的。在C ++中获得多态行为的唯一方法是使用指针(如您的goodDog示例所示)或使用引用。引用(例如Animal&)可以引用从派生的任何类型的对象,Animal而指针(例如Animal*)可以指向从派生的任何类型的对象Animal。Animal但是,平原永远是Animal,别无其他。诸如Java和C#之类的某些语言具有引用语义,其中(在大多数情况下)变量只是对对象的引用,因此给定Animal rex;,rex实际上只是对某些对象的引用Animal,rex = new Dog()而使对象rex引用新Dog对象。C ++不能那样工作:C ++中变量不引用对象,变量是对象。如果您rex = Dog()用C ++讲,它会将一个新Dog对象复制到中rex,并且由于rex实际上是类型Animal,因此将对其进行切片,而仅Animal复制部分。这些称为值语义,这是C ++中的默认语义。如果要在C ++中使用引用语义,则需要显式使用引用或指针(这两个引用与C#或Java中的引用都不相同,但是更相似)。

慕田峪4524236

Animal badDog = Dog();&nbsp; &nbsp; ad.makeSound();实例化a Dog并将其按值分配给Animal变量时,将对对象进行切片。基本上,这意味着您要剥离所有Dog-ness badDog并将其加入基类。为了对基类使用多态,必须使用指针或引用。
打开App,查看更多内容
随时随地看视频慕课网APP