如何使用std::bind绑定纯虚函数接口的成员方法?
问题描述
我们有如下类层次结构:
class Add3Interface { virtual int add3 (const int&) const = 0; }; class Add3: public Add3Interface { virtual int add3 (const int& arg) const override { return arg + 3; } };
我希望绑定add3方法,用于std::views::transform这类场景。绑定具体类Add3的方法可以正常运行:
const Add3 myAdder{}; const auto myFun = std::bind(&Add3::add3, myAdder, std::placeholder::_1);
但我的场景中无法访问具体类型,只能通过Add3Interface接口操作,尝试以下代码时编译器报错:
auto foo(Add3Interface& myAdder) { const auto myFun = std::bind(&Add3Interface::add3, myAdder, std::placeholders::_1); // ... }
错误信息:
/usr/include/c++/11/tuple:238:13: error: cannot declare field ‘std::_Head_base<0, Add3Interface, false>::_M_head_impl’ to be of abstract type ‘Add3Interface’
我试过用typeid解决但出现语法错误,虽然可以用lambda实现:
const auto myFun = [&myAdder] (const auto& arg) { return myAdder.add3(arg); };
但从语义上更偏好使用std::bind,请问该如何实现?
解决方案
问题出在std::bind的参数传递方式上:当你直接传入myAdder(Add3Interface&类型)时,std::bind会默认拷贝这个参数,但Add3Interface是抽象类,无法实例化,自然不能拷贝,这就是报错的原因。
要解决这个问题,你需要让std::bind保存对象的引用而非拷贝,使用std::ref(或std::cref如果对象是const引用)来包装参数:
auto foo(Add3Interface& myAdder) { const auto myFun = std::bind(&Add3Interface::add3, std::ref(myAdder), std::placeholders::_1); // 使用myFun... }
如果myAdder是const引用,就用std::cref:
auto foo(const Add3Interface& myAdder) { const auto myFun = std::bind(&Add3Interface::add3, std::cref(myAdder), std::placeholders::_1); // 使用myFun... }
这样std::bind内部会保存一个引用包装器,不会尝试拷贝抽象类对象,就能正常绑定虚方法,后续调用时会自动转发到实际的派生类实现。
内容的提问来源于stack exchange,提问作者antonio
相关产品推荐
相关产品推荐

