请考虑以下代码:
void foo()
{
std::cout << "A\n";
}
void bar()
{
std::cout << "B\n";
}
// returns a callable object which either refers to foo or bar
// depending on user input during runtime
std::function<void()> maker()
{
std::cout << "Please give a number:\n";
auto x = 0.0;
if (std::cin >> x && x > 50.0)
{ // if we get a valid value from the console and if it is > 50
// we return a callable that refers to foo
return{ &foo };
}
// otherwise we return a callable that refers to bar
return{ &bar };
}
Run Code Online (Sandbox Code Playgroud)
一个简单的调用foo或者bar可以在编译时解决(函数绑定可以在编译期间早期发生)但是使用maker()会导致后期绑定,因为编译器实际上不知道将调用哪个函数:
auto f = maker();
f(); // whether foo or bar is called depends
// on the user input during maker execution
Run Code Online (Sandbox Code Playgroud)
所有其他动态调度方法(即虚函数调用)也是如此.
如果编译器无法(在编译时)证明(运行时信息的缺失)在程序流的某个点调用特定函数,则使用后期函数绑定来解析运行时的相应操作.否则,早期函数绑定用于在编译时解析调用(可能不一定是实际调用,但也可以通过内联完成).
-O0两者,foo并且bar同时从-O2所述组件输出显示一
call t_deriv_1::f() const
Run Code Online (Sandbox Code Playgroud)
在汇编中bar因为make_bar已知bar编译时被检查发现实际返回的类型总是如此t_deriv_1.
struct t_base
{
virtual int f() const = 0;
virtual ~t_base() {}
};
struct t_deriv_1 : t_base
{
int f() const override final;
};
struct t_deriv_2 : t_base
{
int f() const override final;
};
t_base * make_foo();
t_base * make_bar()
{
return new t_deriv_1;
}
void foo()
{
t_base * p = make_foo();
p->f();
delete p;
}
void bar()
{
t_base * p = make_bar();
p->f();
delete p;
}
Run Code Online (Sandbox Code Playgroud)