【问题标题】:C++ virtual functions unexpected behaviorC++ 虚函数意外行为
【发布时间】:2014-01-20 17:33:10
【问题描述】:

我有这条鳕鱼:

class First{
public:
    virtual void print(){cout<<"First";}

};

class Second : public First {
public:
     virtual void print(){cout<<"Second";}


};
class Third : public Second{
public:
   void print(){cout<<"Third";}

  int main(){
    Third ob;
    ob.print();
    Second& sec=ob;
    sec.print();
    First& frs=ob;
    frs.print();
}

一切都如我所料,所有 3 打印:“第三”。

现在因为我的代码太多了,基本都是一样的,稍加改动我会在文中讨论。

现在我从 First 中的 print 中删除 virtual 并打印出:“Third Third First”,正如我所料。

第三次,我将虚拟放回 First,但我将其从 Second 中删除。现在它打印: “三三三”。嗯,这不是我所期望的。假设当使用引用 First 时,它看到函数是虚拟的,然后检查对象并调用 Third 的方法,但是当使用引用 Second 时,它看到函数不是虚拟的,为什么它仍然调用 Third 的打印?

【问题讨论】:

  • 这是因为您使用的是第三个对象的引用。即使您强制转换类型,运行时 vtable 仍将其视为第三
  • Second 中的函数是隐式虚函数,因为它与First 中的函数具有相同的签名。
  • 请注意,将Second 中的print 标记为final 会在出现Third 时给您一个明显的错误。
  • @dyp 如果您想发表您的评论作为答案,我会接受。
  • @StefanStojkovski Mike Seymour 的回答基本相同(当您知道覆盖 == 基类函数是虚拟的并且具有相同/协变签名时)。

标签: c++ class inheritance virtual


【解决方案1】:

如果一个函数覆盖了一个虚函数,那么无论你是否明确声明它都是虚函数。所以这里Second::print 是虚拟的,但是你声明它。

【讨论】:

    【解决方案2】:

    如果函数被声明为虚函数或在其任何基类中被声明为虚函数(当通过指针或引用调用时),则该函数被视为虚函数。

    【讨论】:

      【解决方案3】:

      最后一种情况的行为是预期的。您正在使用对 Third 类型对象的引用。所以这个类的虚函数在所有三个调用中都会被调用。您删除了类 Second 中的函数声明,但 cvlass 从类 First 继承了此函数。它只是不会覆盖它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-16
        相关资源
        最近更新 更多