【问题标题】:C++ inheritance - why is parent method called? [duplicate]C++ 继承 - 为什么调用父方法? [复制]
【发布时间】:2020-01-23 18:00:41
【问题描述】:

我正在实现一个类层次结构并看到对父方法的调用,但我不明白这是为什么。使用 C++11 结构,这是我第一个使用一些特性的 11 个项目,因此我相信这可能是一个良性问题。

class A{
   void update(){
       std::err << "Calling A update " << std::endl;
   } 
}

class B: public A{
   void update(){
       std::cout << "In B update! " << std::endl;
   } 
}

class C: public A{
   void update(){
       std::cout << "In C update! " << std::endl;
   } 
}

现在在其他地方我有一个包含 Bs 或 Cs 的向量

std::vector<A> container;
container.push_back(B());
container.push_back(C());

for(auto item: container){
    item.update();
}

打印

Calling A update
Calling A update

为什么?

【问题讨论】:

  • 阅读object slicing。此外,由于update 不是虚拟的,如果container 是经过适当其他更改的vector&lt;A*&gt;,A 的update 仍将被调用。
  • 关注问题:为什么container.push_back(B()); 合法?似乎这样的代码永远不可取,尤其是链接答案中描述的 Frankenobjects。虽然紧急行为是现有规则的一个可以理解的后果,但添加一条新规则来禁止(或至少发出相对较低级别的警告)这种不良行为似乎是一个可靠的计划……尽管可能会破坏现有代码(即已经以不同的方式破坏了,但仍然如此)。呃。
  • @MarkStorer 几乎从来没有需要复制基类子对象。这是一个有用的功能。您可以将类抽象化以使其非法。

标签: c++ c++11 inheritance


【解决方案1】:

为什么要调用父方法?

因为向量包含父对象。

它包含 Bs 和 Cs,子对象。

它不包含那些对象。它是A 对象的向量,因此它只包含A 类型的对象,不包含任何其他类型的对象。您从派生对象中复制了基类子对象(此操作称为切片)。副本不是基类子对象,而是单独的A 对象。

此外,您的派生类不会覆盖父类函数。只有虚函数可以被覆盖。虚拟调度只能通过指针或对基类子对象的引用间接调用虚函数来使用。

附:您也不能从类外部调用私有成员函数。示例程序格式不正确。

【讨论】:

  • 它包含 Bs 和 Cs,子对象。它被定义为包含从 A 派生的任何内容。因此对象的函数指针更新应该指向各自的类定义?
  • @ElDude 查看编辑。
  • 也许我在这里使用 Python 混淆了我的理解......认为这是常规重载吗?
  • @ElDude Python 是另一种语言。您不能假设继承或其他任何东西在所有语言中都一样有效。 Python 没有值对象的概念,这里有一个值向量。
  • 谢谢。是的,在 Python 上花费了太多时间。必须把那些蟒蛇护目镜摘下来,重新磨一下我的 C++ 护目镜。
【解决方案2】:

向量存储A 的实例,而不是BC,尽管它们是子级。当您将BC 添加到容器时,它向下转换A,并且您会丢失与BC 关联的信息。因此,当您对项目调用 update() 方法时,它会为每个项目调用 A::update

【讨论】:

  • 嗯,如何在 C++ 中创建容器,以便遍历内容会在运行时调用正确的方法(不涉及强制转换)...?
  • 这就是虚函数的用途。您可以将update 方法设为virtual,然后存储基类类型的引用或指针,虚拟调度将为您调用正确的函数。
  • 好的,我缺少 virtual 关键字。谢谢。我认为在没有关键字的情况下无论如何都会发生重载。谢谢
  • 请注意,虚拟调度 only 通过引用和指针发生。如果你在向量中继续持有A 的类型,它将不起作用。
猜你喜欢
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 2021-08-02
  • 2019-11-06
  • 2021-10-03
  • 2015-04-12
  • 2015-01-19
  • 2013-12-25
相关资源
最近更新 更多