【问题标题】:Overriden function getting hiden even after a dynamic cast (upcast)即使在 dynamic_cast (upcast) 之后,覆盖函数也会被隐藏
【发布时间】:2021-07-06 23:23:08
【问题描述】:

我开始学习动态转换以及它如何使用 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 函数?

【问题讨论】:

  • Base* b = dynamic_cast&lt;Base*&gt;(d); 仅相当于 Base* b = d;。此行不会触及类内部的 vtable 指针。它在创建对象时指向 Derived 的 vtable(因为它是它的类型),并且在转换后它继续指向该 vtable。
  • 如果你不想这样,那么不要让foo虚拟。见live
  • 如果你确实想要虚拟,但需要调用Base::foo,然后明确调用它b-&gt;Base::foo();。见live
  • 这就是多态的用途。您可以拥有指向基类的指针并调用为派生版本定义的方法。更好的例子是有一个基指针数组和多个版本的派生类。

标签: c++ casting dynamic-cast static-cast


【解决方案1】:

引用cppreference(粗体是我的):

虚函数是成员函数,其行为可以 在派生类中被覆盖。与非虚函数相反, 即使没有编译时,也会保留覆盖行为 关于类的实际类型的信息。也就是说,如果一个 派生类使用指针或对基类的引用来处理, 调用被覆盖的虚函数将调用行为 在派生类中定义。这样的函数调用称为虚拟 函数调用或虚调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 2015-02-15
    相关资源
    最近更新 更多