c++ - 即使在动态转换(向上转换)之后,被覆盖的函数也会被隐藏
问题描述
我开始了解动态转换以及它如何使用 RTTI 来确定向下转换的对象类型。在这个例子中,我做了一个向上转换,从派生类到基类。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void foo()
{
cout<<"Base"<<endl;
}
};
class Derived : public Base
{
public:
void foo()
{
cout<<"Derived"<<endl;
}
};
int main()
{
Derived* d = new Derived();
Base* b = dynamic_cast<Base*>(d); //(1)
cout<<typeid(b).name()<<endl;
b->foo();
return 0;
}
程序打印:
PBase
Derived
为了我:
- 在编译过程中,编译器为基类创建了一个 vTable,其中我们有一个指向 RTTI“表”的指针,以及一个指向 Base::foo 函数的指针。
- 在执行的时候,当程序到达第(1)行时,他创建了一个指向这个vTable的_vptrBase指针。
我的问题是:当我们调用 foo 函数时,程序如何打印“Derived”?为什么它不调用 Base::foo 函数?
解决方案
引用cppreference(粗体是我的):
虚函数是成员函数,其行为可以在派生类中被覆盖。与非虚拟函数相反,即使没有关于类的实际类型的编译时信息,也会保留覆盖行为。也就是说,如果派生类是使用指针或对基类的引用来处理的,那么对被覆盖的虚函数的调用将调用派生类中定义的行为。这样的函数调用称为虚函数调用或虚调用。
推荐阅读
- rest - IBM BPM JS 从另一个工具包调用外部服务(来自依赖项)
- c# - Mongo UpdateOne 使用 Lambda 和 FieldDefinition 将子文档添加到数组 C#
- kivy - 打包 kivymd 应用程序时发生错误
- java - 在 coordinatorlayout 中未滚动时如何隐藏标题
- reactjs - 如何在 React 中记忆组件列表的一部分
- javascript - 如何使用 for 循环动态创建对象属性和赋值
- amazon-web-services - 将文件写入 csv 并存储到 S3 时无法更改文件名
- python - 删除文本字段时的 Tkinter 问题
- database - 是否有一个开源组件可以订阅各种数据库活动提要并使 Redis 等进程外缓存失效?
- sql - SQL - 使用 JOIN 或 SUM 时的双倍(或三倍)计数统计信息