绑定纯虚法

Bind pure virtual method

提问人:Antonio 提问时间:9/6/2023 最后编辑:Ted LyngmoAntonio 更新时间:9/6/2023 访问量:83

问:

假设我们有以下层次结构:

class Add3Interface {
  virtual int add3 (const int&) const = 0;
};

class Add3: public Add3Interface {
  virtual int add3 (const int& arg) const override {
    return arg + 3;
  }
};

我想绑定该方法,以便我可以在类似的事情中使用它。 以下代码很好:add3std::views::transform

const Add3 myAdder{};
const auto myFun = std::bind(&Add3::add3, myAdder, std::placeholder::_1);

但是,在我的用例中,我无法访问具体类型,因此我必须编写如下内容:

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

const auto myFun = std::bind(&(typeid(myAdder)::add3), myAdder, std::placeholders::_1);

但这只会导致各种语法错误,这些错误取决于我如何放置各种括号。

当然,我们可以只使用lambda:

const auto myFun = [&myAdder] (const auto& arg) { return myAdder.add3(arg); };

但如果可能的话,我更愿意使用,因为我觉得它代表了我从语义角度试图做得更好的地方。bind

C++ 纯虚拟 stdbind

评论

2赞 n. m. could be an AI 9/6/2023
, myAdder, => , std::ref(myAdder),
0赞 Remy Lebeau 9/6/2023
@n.m.couldbeanAI,应该作为答案而不是评论发布
0赞 Antonio 9/6/2023
从复制各个位时的滑移派生。我编辑了这个问题。Add3Interface
0赞 Eljay 9/6/2023
我认为 lambda 从语义的角度更好地代表了您想要做得更好的事情。(现在我们有了 lambda,可以走 .std::bindstd::auto_ptr

答:

3赞 HTNW 9/6/2023 #1

std::bind尝试按值存储其所有参数。在本例中,它尝试复制到 类型的数据成员中。当然,抽象地说,这是失败的。问题不在于成员函数指针的类型错误。myAdderAdd3InterfaceAdd3Interface

如果要通过引用引用存储的参数,请传递 .您可以使用便利函数或构造 s。std::bindstd::reference_wrapper<T>Tstd::refstd::crefstd::reference_wrapper

auto foo(Add3Interface& myAdder) {
    const auto myFun = std::bind(&Add3Interface::add3, std::ref(myAdder),
                                 std::placeholders::_1);
    // ...
}

(准确地说,它本身根本没有专门处理。它只会将 的副本存储为数据成员,就像它存储任何其他参数的副本一样。在函数调用时会正确解包,因为许多标准实用程序用于调用可调用对象的标准 INVOKE 操作会解包它。std::bindstd::reference_wrapperstd::reference_wrapperstd::reference_wrapper

0赞 Dmytro Ovdiienko 9/6/2023 #2

但是,在我的用例中,我无法访问具体类型,因此我必须编写这样的东西

如果要传递 的任何实例,可以定义调用成员函数的静态成员函数:Add3Interface

#include <functional>
#include <iostream>

struct Add3Interface {
  virtual int add3 (const int&) const = 0;
  static int staticAdd3 (Add3Interface const& ths, const int& arg) { return ths.add3(arg); }
};


struct Add3: Add3Interface {
  virtual int add3 (const int& arg) const override {
    return arg + 3;
  }
};

struct Add4: Add3Interface {
  virtual int add3 (const int& arg) const override {
    return arg + 4;
  }
};

int main()
{
   auto myFun = std::bind(Add3Interface::staticAdd3, std::placeholders::_1, std::placeholders::_2);
   Add4 add4;
   Add3 add3;
   std::cout << myFun(add3, 1) << "\n";
   std::cout << myFun(add4, 1) << "\n";
}