C++ 学习C++;:多态性与切片
考虑以下示例:C++ 学习C++;:多态性与切片,c++,polymorphism,C++,Polymorphism,考虑以下示例: #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
#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();
}
但我认为输出肯定应该是“生树皮树皮树皮”。那坏蛋怎么了
更新:您可能感兴趣。这是一个称为“切片”的问题
Dog()
创建一个Dog
对象。如果您要调用Dog().makeSound()
,它将按您的预期打印“树皮”
问题是您正在使用此狗
初始化坏狗
,它是动物
类型的对象。由于动物
只能包含动物
而不能包含任何源于动物
的内容,因此它会获取狗
的动物
部分,并使用该部分对自身进行初始化
badDog
的类型总是Animal
;它不可能是别的东西
<> P>你在C++中可以获得多态行为的唯一方法是使用指针(正如你用<代码> GooDoo[</代码>示例]演示的那样)或使用引用。p>
引用(例如,动物&
)可以引用从动物
派生的任何类型的对象,指针(例如,动物*
)可以指向从动物
派生的任何类型的对象。然而,普通的动物
,总是动物
,没有别的
一些语言如Java和C#具有引用语义,其中变量(在大多数情况下)只是对对象的引用,因此给出了Animal-rex
,rex
实际上只是对一些动物的引用,而rex=new Dog()
使rex
引用一个新的Dog
对象
C++不工作:变量不引用C++中的对象,变量是对象。如果在C++中说<代码>雷克斯=DOGER()/CUT>,它将新的<代码>狗< /C>对象复制到<代码>雷克斯< /C>中,并且由于雷克斯 实际上是类型<代码>动物< /代码>,它被切片,并且只是<代码>动物< /代码>部分被复制。这些被称为值语义,这是C++中的默认值。如果你想在C++中引用语义,你需要显式使用引用或指针(这两个都与C语言或java中的引用相同,但是它们更相似)。
当您实例化一只
狗
并通过值将其分配给动物
变量时,您将创建对象。这基本上意味着您从badDog
中去掉所有Dog
-ness,并将其放入基类
为了对基类使用多态性,必须使用指针或引用。您使用赋值运算符初始化了badDog。因此,狗()被复制为动物。程序的输出是正确的。:) 我认为您的变量有一些命名错误。代码甚至不能按原样编译。和void main()???呃……我不明白为什么有人会否决这个问题——它既不是“不清楚”也不是“没用”+1否定否决票。准则“使非叶类抽象化”将防止这一意外。另一个+1用于发布一个完整的、说明问题的最小示例。这正是我们一直要求的。很好的解释。谢谢我将补充说,我已经大大简化了java和C++和C++的类型系统之间的比较。为什么C++对象分配不将VPTR与其余成员一起复制,以获得变量级的PoyLististic?
rawr
bark
rawr
bark
Animal badDog = Dog();
ad.makeSound();