基类指针vs继承类指针?

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)可能没有(我猜测这里,我不会打扰任何编译器检查的要点是:编译器可能使有关不同的假设ad转换代码时).
  • 等等

您可以通过其中任何一个调用Dynamic的虚函数(即定义的多态接口),效果相同.Dog无论如何,假设没有隐藏它们(好的一点,JaredPar).

对于在Animal中定义的非虚函数,以及在Dog中定义(重载)的非虚函数,调用该函数a不同于通过调用它d.


Jar*_*Par 5

这个问题的答案是一个巨人:这取决于

指针的类型可以通过多种方式变得重要。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没有参数的方法,没有重载匹配并且编译失败。