为什么 std::bind 使用引用传递时会阻止后期绑定?
Why does std::bind prevent late binding when using pass-by-reference?
我有一个基 class、一个派生 class 和一个虚拟成员函数。我还有一个函数,它接受一个基 class 引用并对成员函数进行多态调用:
#include <iostream>
#include <functional>
class Base
{
public:
Base() {}
virtual int getnum() { return 1; }
};
class Derived : public Base
{
public:
Derived() {}
virtual int getnum() { return 2; }
};
int getnumref(Base& b) { return b.getnum(); }
int main()
{
Derived d;
Base& bref = d;
std::cout << getnumref(bref) << std::endl;
}
这里发生了后期绑定,输出为2
.
但是如果我现在将以下行添加到 main()
函数中以便预先定义函数的参数,然后调用它:
std::function<int()> boundgetnumref = std::bind(getnumref, bref);
std::cout << boundgetnumref() << std::endl;
那么最后一行的输出是1
,即这里发生了早期绑定,调用了基class的成员函数
如果我使用指针,即
//...
int getnumptr(Base* b) { return b->getnum(); }
//...
int main()
{
Derived d;
Base* bptr = &d;
std::cout << getnumptr(bptr) << std::endl;
std::function<int()> boundgetnumptr = std::bind(getnumptr, bptr);
std::cout << boundgetnumptr() << std::endl;
}
那么两个 cout
调用的输出都是 2
.
为什么当我将引用传递与 std::bind
一起使用时会发生早期绑定,而不是其他情况?
std::bind
按值存储捕获的参数,导致 Derived
的切片副本到 Base
。
如果你只是传递 std::reference_wrapper
(一个指针)来复制指针,那么切片复制就不会发生:
std::function<int()> boundgetnumref = std::bind(getnumref, std::ref(bref));
尽管更喜欢 lambda,它们是最佳实践:更易于编写、阅读且更高效:
auto boundgetnumref = [&bref]() { return getnumref(breg); }
我有一个基 class、一个派生 class 和一个虚拟成员函数。我还有一个函数,它接受一个基 class 引用并对成员函数进行多态调用:
#include <iostream>
#include <functional>
class Base
{
public:
Base() {}
virtual int getnum() { return 1; }
};
class Derived : public Base
{
public:
Derived() {}
virtual int getnum() { return 2; }
};
int getnumref(Base& b) { return b.getnum(); }
int main()
{
Derived d;
Base& bref = d;
std::cout << getnumref(bref) << std::endl;
}
这里发生了后期绑定,输出为2
.
但是如果我现在将以下行添加到 main()
函数中以便预先定义函数的参数,然后调用它:
std::function<int()> boundgetnumref = std::bind(getnumref, bref);
std::cout << boundgetnumref() << std::endl;
那么最后一行的输出是1
,即这里发生了早期绑定,调用了基class的成员函数
如果我使用指针,即
//...
int getnumptr(Base* b) { return b->getnum(); }
//...
int main()
{
Derived d;
Base* bptr = &d;
std::cout << getnumptr(bptr) << std::endl;
std::function<int()> boundgetnumptr = std::bind(getnumptr, bptr);
std::cout << boundgetnumptr() << std::endl;
}
那么两个 cout
调用的输出都是 2
.
为什么当我将引用传递与 std::bind
一起使用时会发生早期绑定,而不是其他情况?
std::bind
按值存储捕获的参数,导致 Derived
的切片副本到 Base
。
如果你只是传递 std::reference_wrapper
(一个指针)来复制指针,那么切片复制就不会发生:
std::function<int()> boundgetnumref = std::bind(getnumref, std::ref(bref));
尽管更喜欢 lambda,它们是最佳实践:更易于编写、阅读且更高效:
auto boundgetnumref = [&bref]() { return getnumref(breg); }