如何使用std::bind()来调用基类的虚函数版本?

11
我正在尝试使用std::bind()创建一个函数,该函数将调用基类版本的虚函数,而不是调用派生类的版本。
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;
}

我从其他地方了解到,通常情况下您无法以“反虚拟”的方式调用基函数,例如此处。明显的例外是常见的范例:

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

由于在Derived的方法中,表达式Base::bar()被认为是“反虚拟化”的(我所指的意思),因此是否可能从Derived的某个方法内以期望的方式绑定到Base::bar()?例如,像这样:

void Derived::bar()
{
    auto baseMethod = std::bind( &Base::foo, this );
    baseMethod();
}
如果是这样,语法是什么?

如果是这样,语法是什么?


为什么不将 Base::bar() 设为非虚成员函数呢? - John
1个回答

17

好的,&Base::foo 是一个成员函数指针。没有方法可以使用成员函数指针而不调用虚拟覆盖。唯一避免虚拟覆盖的语法是类名、函数名和参数列表都在同一表达式中的语法。

但如果您有 std::bind,那么您可能也有 lambda 表达式,因此您可以尝试使用:

auto baseMethod = [this](){ return Base::foo(); };
//...
baseMethod();

抱歉,我没听懂。你怎么能在没有对象的情况下调用成员函数? - balki
1
该 lambda 表达式仅在 BaseDerived 的成员函数中(或另一个 Base 的子类)起作用,并捕获了 this - aschepler
@aschepler,在我的编译器(Apple LLVM Compiler 4.1)中,需要使用this关键字,否则会出现错误:"error: 'this' cannot be implicitly captured in this context."。因此我进行了早期的编辑。 - OldPeculier
是的,[this] 是必要的。已编辑。 - aschepler
据我所见,void Derived::bar() { auto baseMethod = [this](){ return Base::foo(); }; //... baseMethod(); }void Derived::bar() { Base::bar(); }之间没有区别。它们都是“反虚拟函数”。我的理解正确吗? - John
@John 是的,在两者中 Base::func() 强制了非虚拟行为。区别在于创建命名函数和本地可调用变量之间。 - aschepler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接