How do I use std::bind() to call the base class's version of a virtual function?
Asked Answered
K

1

11

I am trying to use std::bind() to create a function that will call the base class version of a virtual function rather than calling the derived class's version.

struct Base
{
    virtual void foo() { cout << "Base\n"; }
};

struct Derived : public Base
{
    virtual void foo() { cout << "Derived\n"; }
};

int main(int argc, const char * argv[])
{
    Base* base = new Derived;
    auto baseMethodHopefully = std::bind( &Base::foo, base );
    baseMethodHopefully();    // Want call to Base::foo(), but get call to Derived::foo().

    return 0;
}

I understand from elsewhere that you can't normally call a base function in an "anti-virtual" way such as this. The obvious exception is the common paradigm:

void Derived::bar() { Base::bar(); }

Since the expression Base::bar() is recognized as "anti-virtual" (in the sense I'm alluding to) within Derived's methods, is it possible to bind to Base::bar() in the desired way from within one of Derived's methods? E.g. something like:

void Derived::bar()
{
    auto baseMethod = std::bind( &Base::foo, this );
    baseMethod();
}

If so, what is the syntax?

Kolk answered 18/1, 2013 at 21:40 Comment(1)
Why not simply make the Base::bar() as a non-virtual member function?Pendentive
L
17

Well, &Base::foo is a member function pointer. And there is no way to use a member function pointer that doesn't invoke a virtual override. The only syntax that avoids virtual overrides is the one where the class name, function name, and argument list are all in the same expression.

But if you have std::bind, you likely also have lambdas, so maybe you could use:

auto baseMethod = [this](){ return Base::foo(); };
//...
baseMethod();
Lackluster answered 18/1, 2013 at 21:53 Comment(6)
Sorry, I didn't get it. How can you can a member function without an object?Liking
That lambda expression only works in a member function of Base or Derived (or another subclass of Base), and captures this.Lackluster
@aschepler, on my compiler (Apple LLVM Compiler 4.1) this is required or I receive an error: "error: 'this' cannot be implicitly captured in this context." Hence my earlier edit.Kolk
Yes, the [this] is necessary. Edited.Lackluster
@Lackluster As far as I can see, there is no difference between void Derived::bar() { auto baseMethod = [this](){ return Base::foo(); }; //... baseMethod(); } and void Derived::bar() { Base::bar(); }. They are both anti-virtual.Am I right?Pendentive
@Pendentive Yes, the Base::func() in both is what forces non-virtual behavior. The difference is between making a named function vs. a local callable variable.Lackluster

© 2022 - 2024 — McMap. All rights reserved.