0

Is there a way to make a pointer on member function in base class if it is a virtual function and it is overridden in derived class?

Consider the code as follows

#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;
}

It prints ‘Derived’ twice despite I make a pointer on Base::g. Is there a way to keep function g virtual and overridden and get member function pointer that will print ‘Base’ for d?

Fedor
  • 17,146
  • 13
  • 40
  • 131

2 Answers2

3

Just call the base function

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;
}

Output

Derived
Base
Base
Base

This can be made a pointer to the function; but it needs be to the member function Base::g() of the object being pointed to.

thelizardking34
  • 338
  • 1
  • 12
2

You might define a non-virtual function real_g called from g so code

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

Then later in main

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

See wikipage on virtual method table, this C++ reference and the C++ standard n3337 or better. Read also a good C++ programming book and the documentation of your C++ compiler, e.g. GCC

See also this answer (explaining naively what are vtables, in simple cases)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    That feels like cheating :) – SergeyA Apr 30 '21 at 18:05
  • No; and a good optimizing compiler generates equivalent code anyway – Basile Starynkevitch Apr 30 '21 at 18:07
  • 1
    Yet it does. The biggest problem here is that enabling the class to work in a manner desired by OP requires class modifications. First of all, it might not be feasible at all (class might come from third-party library), second of all, it causes expansion of functions members. I do not claim to know how to achieve what OP wants (otherwise I would post an answer), but I do not like this answer either. – SergeyA Apr 30 '21 at 18:14
  • 2
    This doesn't actually solve the question of "Is there a way to keep function g virtual and overridden and get member function pointer that will print 'Base of d' – thelizardking34 Apr 30 '21 at 18:14
  • 2
    @thelizardking34 technically it does - `g` is still overridden and virtual - but yes, it feels like cheating on the technicality. – SergeyA Apr 30 '21 at 18:15
  • 1
    @SergeyA If you're going to add extra functions; why not just wrap it in a lambda instead of changing the functionality of the class; and depending on the compiler to make it better? – thelizardking34 Apr 30 '21 at 18:29
  • @BasileStarynkevitch Could we do std::mem_fn(&Base::g)(static_cast(d))? – Jimmy Loyola Apr 30 '21 at 20:20
  • @JimmyLoyola, by doing so you will create a copy of d, which is not what was expected: create a pointer/callable function to Base::g of existing object d. – Fedor May 15 '21 at 08:58