为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++
www说 2019-09-24 16:32:54
考虑以下示例:#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();}输出为:rawrbarkrawrbark但是我认为输出肯定应该是“ raw kark bark bark”。badDog怎么了?更新:您可能对我的另一个问题感兴趣。
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

这是一个称为“切片”的问题。

Dog()创建一个Dog对象。如果您要致电Dog().makeSound(),它将按您期望的那样打印“树皮”。

问题是,你是初始化badDog,这是类型的对象Animal,与此Dog。由于Animal只能包含Animal和,而不能包含从派生的任何内容Animal,因此它会占用的Animal一部分Dog并以此进行初始化。

的类型badDog总是Animal; 它永远不可能是别的。

在C ++中获得多态行为的唯一方法是使用指针(如您的goodDog示例所示)或使用引用。

引用(例如Animal&)可以引用从派生的任何类型的对象,Animal而指针(例如Animal*)可以指向从派生的任何类型的对象AnimalAnimal但是,平原永远是Animal,别无其他。

诸如Java和C#之类的某些语言具有引用语义,其中(在大多数情况下)变量只是对对象的引用,因此给定Animal rex;rex实际上只是对某些对象的引用Animalrex = new Dog()而使对象rex引用新Dog对象。

C ++不能那样工作:C ++中变量不引用对象,变量是对象。如果您rex = Dog()用C ++讲,它会将一个新Dog对象复制到中rex,并且由于rex实际上是类型Animal,因此将对其进行切片,而仅Animal复制部分。这些称为值语义,这是C ++中的默认语义。如果要在C ++中使用引用语义,则需要显式使用引用或指针(这两个引用与C#或Java中的引用都不相同,但是更相似)。


查看完整回答
反对 回复 2019-09-24
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

Animal badDog = Dog();

    ad.makeSound();

实例化a Dog并将其按值分配给Animal变量时,将对对象进行切片。基本上,这意味着您要剥离所有Dog-ness badDog并将其加入基类。


为了对基类使用多态,必须使用指针或引用。


查看完整回答
反对 回复 2019-09-24
  • 3 回答
  • 0 关注
  • 432 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信