c++ - 调用虚函数的逻辑不清晰(或者是方法隐藏?)

标签 c++ class inheritance overriding virtual

(在msvc2017上测试)

struct AAA
{
    virtual float run(int arg)
    {
        return 5.5f;
    }
};

struct BBB : AAA
{
    virtual bool run(double arg)
    {
        return false;
    }
};

struct CCC : BBB
{
    virtual float run(int arg)
    {
        return 7.7f;
    }

    virtual bool run(double arg)
    {
        return true;
    }
};


CCC c;
BBB* pb = &c;
pb->run(5); // call CCC::run(double arg), WHY?? 
pb->run((int)5); // call CCC::run(double arg), WHY?? 

为什么 pb->run(5) 只调用 CCC::run(double arg) 而不是 CCC::run(int arg) ?

具有不同签名的子类的虚方法是否与基类的接口(interface)重叠?

最佳答案

一切都很简单。

BBB 类实际上有两个虚函数。一个在其基类 AAA 中声明

struct AAA
{
    virtual float run(int arg)
    {
        return 5.5f;
    }
};

其他在类 BBB 本身中声明。

struct BBB : AAA
{
    virtual bool run(double arg)
    {
        return false;
    }
};

类 BBB 中声明的函数隐藏了类 AAA 中声明的函数。 (在派生类中声明的任何名称都隐藏了在派生类的基类中声明的同名实体)

在 CCC 类中,这两个函数都被覆盖了。

这些函数调用

pb->run(5); // call CCC::run(double arg), WHY?? 
pb->run((int)5); // call CCC::run(double arg), WHY?? 

没有区别,因为它们的参数类型为 int

指针pb的静态类型是BBB *。因此编译器在类 BBB 中搜索名称 run。

在类中只有一个同名的函数是可见的。是类中声明的函数

virtual bool run(double arg)
{
    return false;
}

因此,编译器使用此签名运行此虚函数,但使用为类 CCC 定义的虚函数指针表调用它,因为指针 pb 的动态类型是 CCC *.

您可以通过 using 声明使类 AAA 中声明的函数在类 BBB 中可见。例如

struct BBB : AAA
{
    using AAA:: run;
    virtual bool run(double arg)
    {
        return false;
    }
};

在这种情况下,函数的声明(在 AAA 类中声明)也是 BBB 类中的成员声明。也就是说 BBB 类将有两个重载的不同虚函数的声明。

这是一个演示程序

#include <iostream>

struct AAA
{
    virtual float run(int arg)
    {
        return 5.5f;
    }
};

struct BBB : AAA
{
    using AAA:: run;
    virtual bool run(double arg)
    {
        return false;
    }
};

struct CCC : BBB
{
    virtual float run(int arg)
    {
        return 7.7f;
    }

    virtual bool run(double arg)
    {
        return true;
    }
};

int main() 
{
    CCC c;
    BBB* pb = &c;
    std::cout << pb->run(5) << '\n';
    std::cout << pb->run(5.6 ) << '\n';

    return 0;
}

它的输出是

7.7
1

为了使派生类及其基类中的成员声明的情况更清楚,请考虑 block 作用域的类似情况。

这是一个演示程序

#include <iostream>

void f( int ) { std::cout << "void f( int )\n"; }
void f( double ) { std::cout << "void f( double )\n"; }

int main() 
{
    void f( double );

    f( 5 );
    f( 5.5 );

    return 0;
}

函数 main block 范围内的函数 f 的内部声明隐藏了函数在全局范围内的其他声明。

程序输出为

void f( double )
void f( double )

关于c++ - 调用虚函数的逻辑不清晰(或者是方法隐藏?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57577757/

相关文章:

java - Java 类可以拥有的最大方法数是多少?

c++ - Mixin 构造函数嵌套包扩展

java - 显示 ArrayList 中对象的值(来自子类)(基于父类(super class))

c++ - 原型(prototype)模式

c++ - 在 C/C++ 中重构数字

c++ - 对表格进行排序 C++

javascript - Odoo 更改基本 JavaScript 方法

python - 如何在列表中查找对象并在pygame中进行比较?

java - 所有类如何继承自Object?

C++,运行时错误 : member call on null pointer of type