问题发生的情况
请考虑以下 C++ 代码:
#include <functional>
#include <iostream>
#include <string>
// Superclass
class A {
public:
virtual std::string get() const {
return "A";
}
};
// Subclass
class B : public A {
public:
virtual std::string get() const {
return "B";
}
};
// Simple function that prints the object type
void print(const A &instance) {
std::cout << "It's " << instance.get() << std::endl;
}
// Class that holds a reference to an instance of A
class State {
A &instance;
public:
State(A &instance) : instance(instance) { }
void run() {
// Invokes print on the instance directly
print(instance);
// Creates a new function by binding the instance
// to the first parameter of the print function,
// then calls the function.
auto func = std::bind(&print, instance);
func();
}
};
int main() {
B instance;
State state(instance);
state.run();
}
在这个例子中,我们有两个类A
and B
. B
从类继承A
。这两个类都实现了一个返回类型名称的简单虚拟方法。
还有一个简单的方法,print
,它接受对实例的引用A
并打印类型。
班上State
持有对实例的引用A
。该类还有一个简单的方法,调用print
通过两种不同的方式。
哪里变得奇怪
状态中唯一的方法首先调用print
直接地。由于我们提供了一个实例B
int main 方法,输出是It's B
,正如预期的那样。
然而,对于第二次调用,我们将实例绑定到第一个参数print
using std::bind
。然后我们不带任何参数调用结果函数。
然而,在这种情况下,输出是It's A
。我本来期望输出It's B
,和以前一样,因为它仍然是同一个实例。
如果我将参数声明为指针而不是引用,std::bind
按预期工作。我还在两个类的构造函数中放置了一些日志记录,以验证没有意外创建实例。
为什么会出现这种情况?做std::bind
在这种情况下丢弃一些类型信息?据我了解,这种情况一定不会发生,因为方法调用应该由运行时的 vtable 查找来管理。