指向基虚拟成员函数的指针

问题描述

如果基类中的成员函数是虚函数并且在派生类中被覆盖,有没有办法在基类中的成员函数上创建指针?

考虑如下代码

#include <iostream>
#include <functional>

struct Base
{
    virtual void g() const
    {
        std::cout << "Base" << std::endl;
    }
};

struct Derived : Base
{
    virtual void g() const override
    {
        std::cout << "Derived" << std::endl;
    }
};

int main()
{
    Derived d;
    (d.*(&Base::g))();
    std::mem_fn(&Base::g)(d);
    return 0;
}

尽管我在 Base::g 上做了一个指针,它还是打印了两次“Derived”。有没有办法让函数 g 保持虚拟和覆盖,并获得将为 d 打印“Base”的成员函数指针?

解决方法

只需调用基本函数

int main()
{
    Derived d;
    d.g();
    
    Base* b = &d;
    b->Base::g();
    
    //or 
    d.Base::g();

    //or

    auto callLater = [&d]() { d.Base::g();};
    callLater();
    return 0;
}

输出

Derived
Base
Base
Base

这可以做成一个指向函数的指针;但它需要指向所指向对象的成员函数 Base::g()。

,

您可以定义一个从 real_g 调用的非虚拟函数 g so code

struct Base
{
  void real_g() const {
    std::cout << "Base" << std::endl;
  }
  virtual void g() const { real_g(); };
};

然后在main

std::mem_fn(&Base::real_g)(d);

请参阅关于 virtual method tablethis C++ reference 和 C++ 标准 n3337 或更好的维基页面。另请阅读 good C++ programming book 和 C++ 编译器的文档,例如GCC

另见 this 答案(在简单的情况下天真地解释什么是 vtable)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...