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?

Community
  • 1
  • 1
OldPeculier
  • 11,049
  • 13
  • 50
  • 76

1 Answers1

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();
aschepler
  • 70,891
  • 9
  • 107
  • 161
  • Sorry, I didn't get it. How can you can a member function without an object? – balki Jan 19 '13 at 06:07
  • 1
    That lambda expression only works in a member function of `Base` or `Derived` (or another subclass of `Base`), and captures `this`. – aschepler Jan 19 '13 at 06:58
  • @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. – OldPeculier Jan 21 '13 at 23:46
  • Yes, the `[this]` is necessary. Edited. – aschepler Dec 08 '15 at 17:42
  • @aschepler 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? – John Aug 15 '21 at 06:55
  • @John 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. – aschepler Aug 15 '21 at 18:23