目标是让函子到达 Base::Print。
#include <functional>
#include <iostream>
using namespace std;
class Base {
public:
virtual void Print() {
cout << "Base" << endl;
}
virtual function<void()> get_fx1() {
return bind(&Base::Print, this);
}
virtual function<void()> get_fx2() {
return bind(&Base::Print, *this);
}
};
class Derived : public Base {
public:
virtual void Print() override {
std::cout << "Derived" << std::endl;
}
};
int main()
{
Derived d;
Base *ptr = &d;
ptr->Base::Print(); // prints Base (expecetd) #out1
bind(&Base::Print, ptr)(); // prints Derived (expected Base) #out2
ptr->get_fx1()(); // prints Derived (expected Base) #out3
ptr->get_fx2()(); // prints Base (expected Derived because of out2 and out3) #out4
cout << " -- " << endl;
Derived d2;
Base& ref = d2;
ref.Base::Print(); // prints Base (expected) #out5
bind(&Base::Print, ref)(); // prints Base (expected Derived because of out2 and out3. But this matches the behaviour with out4) #out6
cout << " -- " << endl;
(&ref)->Base::Print(); // prints Base (expected) #out7
bind(&Base::Print, &ref)(); // prints Derived (I give up) #out8
return 0;
}
我假设传递指针或引用到 std::bind 是完全相同的。显然,我错了。似乎当引用传递给 std::bind 时,您可以阻止 vtable 查找。但是当指针传递给 std::bind 时,无法阻止 vtable 查找。根据经验,这就是看起来的样子。
所以,问题是:当传递引用时,std::bind 是否有选择地跳过 vtable 查找?
我没有找到任何参考资料仅说明这一点。
编辑: 链接到 编译器资源管理器
std::bind
无法绑定引用,您正在将派生类切片到基类,并在切片对象上调用虚函数。为此,虚拟调用正确调用了基类函数。