pep*_*dip 0 c++ methods virtual inheritance class
我自己学习c ++并且遇到了一个我没想到的行为.我不确定,但确实认为这不是Java在类似情况下会做的事情.为什么是Dog和Cat依靠TE父类的实现,使一个普通的声音?
#include <iostream>
class Animal{
public:
virtual void speak(){std::cout << "???" << std::endl; /* not implemented */}
};
class Dog : public Animal{
public:
virtual void speak(){
std::cout << "Woof" << std::endl;
}
};
class Cat : public Animal{
public:
virtual void speak(){
std::cout << "Meow" << std::endl;
}
};
class Desk{
/* Not an animal */
};
template<class T>
void please_talk(){
T anim;
Animal ani = anim;
anim.speak();
ani.speak();
}
int main()
{
please_talk<Dog>();
please_talk<Cat>();
/* Does not compile please_talk<Desk>(); */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果:
Woof
Generic animal sound
Meow
Generic animal sound
Run Code Online (Sandbox Code Playgroud)
Animal ani = anim;
Run Code Online (Sandbox Code Playgroud)
Animal无论类型如何,都会创建一个新的类型对象anim.所以ani.speak()会调用Animal::speak,因为这是类型的覆盖Animal.
如果你要创建一个引用(或指针)
Animal & ani = anim;
Run Code Online (Sandbox Code Playgroud)
那么动态类型将被保留,T::speak并将被调用.这类似于复制对象引用时Java中发生的情况; 但是你不应该试图用Java来理解C++对象模型,因为它们非常不同.
您可以通过使基类抽象来防止意外创建基类对象(有时称为"切片",因为它会切除对象的派生类部分).也就是说,使用默认实现声明函数pure virtual,而不是非pure:
virtual void speak() = 0; // Really not implemented
Run Code Online (Sandbox Code Playgroud)
抽象类无法实例化为完整对象,因此如果您尝试这将导致编译时错误.