【问题标题】:Pointer to a base virtual member function指向基本虚拟成员函数的指针
【发布时间】:2021-04-30 17:54:40
【问题描述】:

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

考虑如下代码

#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”的成员函数指针?

【问题讨论】:

    标签: c++ pointers polymorphism pointer-to-member


    【解决方案1】:

    只需调用基函数

    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()。

    【讨论】:

      【解决方案2】:

      你可以定义一个非虚函数real_gg调用所以代码

      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 答案(在简单的情况下天真地解释什么是 vtables)

      【讨论】:

      • 感觉像是在作弊:)
      • 然而确实如此。这里最大的问题是使类以 OP 所需的方式工作需要修改类。首先,它可能根本不可行(类可能来自第三方库),其次,它会导致函数成员的扩展。我不声称知道如何实现 OP 想要的(否则我会发布答案),但我也不喜欢这个答案。
      • 这实际上并没有解决“有没有办法让函数 g 保持虚拟并被覆盖并获得将打印 'Base of d' 的成员函数指针”的问题
      • @thelizardking34 在技术上确实如此 - g 仍然被覆盖和虚拟 - 但是是的,感觉就像在技术上作弊。
      • @SergeyA 如果你要添加额外的功能;为什么不将它包装在 lambda 中而不是更改类的功能;并依赖编译器让它变得更好?
      猜你喜欢
      • 1970-01-01
      • 2011-07-01
      • 2021-10-31
      • 2015-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 2018-03-24
      相关资源
      最近更新 更多