Vla*_*ala 5 c++ polymorphism inheritance
假设我有一个Dog
继承自类的类Animal
.这两行代码有什么区别?
Animal *a = new Dog();
Dog *d = new Dog();
Run Code Online (Sandbox Code Playgroud)
在一个中,指针用于基类,而在另一个中,指针用于派生类.但这种区别何时变得重要?对于多态性,任何一个都可以完全相同,对吧?
Ste*_*sop 11
对于类型检查的所有目的,编译器将其a
视为可以指向任何Animal,即使您知道它指向Dog:
a
给期望的函数Dog*
.a->fetchStick()
,fetchStick
成员函数在哪里Dog
但不是Animal
.Dog *d2 = dynamic_cast<Dog*>(d)
可能只是编译器上的指针副本.Dog *d3 = dynamic_cast<Dog*>(a)
可能没有(我猜测这里,我不会打扰任何编译器检查的要点是:编译器可能使有关不同的假设a
和d
转换代码时).您可以通过其中任何一个调用Dynamic的虚函数(即定义的多态接口),效果相同.Dog
无论如何,假设没有隐藏它们(好的一点,JaredPar).
对于在Animal中定义的非虚函数,以及在Dog中定义(重载)的非虚函数,调用该函数a
不同于通过调用它d
.
这个问题的答案是一个巨人:这取决于
指针的类型可以通过多种方式变得重要。C++ 是一种非常复杂的语言,它出现的方式之一就是继承。
让我们举一个简短的例子来演示这可能很重要的多种方式之一。
class Animal {
public:
virtual void MakeSound(const char* pNoise) { ... }
virtual void MakeSound() { ... }
};
class Dog : public Animal {
public:
virtual void MakeSound() {... }
};
int main() {
Animal* a = new Dog();
Dog* d = new Dog();
a->MakeSound("bark");
d->MakeSound("bark"); // Does not compile
return 0;
}
Run Code Online (Sandbox Code Playgroud)
原因是 C++ 进行名称查找的方式的一个怪癖。简而言之:在寻找调用 C++ 的方法时,将遍历类型层次结构,寻找具有匹配名称的方法的第一个类型。然后它将从在该类型上声明的具有该名称的方法中寻找正确的重载。由于Dog
只声明了一个MakeSound
没有参数的方法,没有重载匹配并且编译失败。