【问题标题】:Delegate in C++11C++11 中的委托
【发布时间】:2010-09-01 22:49:22
【问题描述】:

C++11 是否提供委托?

如果不是,在 C++ 中做类似事情的最佳(最有效)方法是什么?升压信号?快速代理?还有什么?

【问题讨论】:

  • 函数指针有什么问题?
  • 我不能将它与类方法一起使用:/
  • 是的,你可以 parashift.com/c++-faq-lite/pointers-to-members.html 但可能有更好的东西可以使用,例如C++ 函数不需要是方法,或者你可以把类变成仿函数

标签: c++ delegates c++11


【解决方案1】:

您可以使用bind 将成员函数绑定到类实例来获得类似委托的语义:

#include <functional>

struct C 
{
    void Foo(int) { }
};

void Bar(std::function<void(int)> func) 
{ 
    func(42); // calls obj.Foo(42)
}

int main() 
{
    using namespace std::placeholders;

    C obj;
    Bar(std::bind(&C::Foo, obj, _1));
}

在此示例中,Bar() 采用具有单个 int 参数并返回 void 的任何内容。

main() 中,我们将指向成员函数C::Foo 的指针绑定到名为objC 实例。这为我们提供了一个可以使用单个 int 参数调用并返回 void 的对象。

我们用这个对象调用Bar()Bar() 调用obj.Foo(42)

【讨论】:

  • @jk:只是有时。显然在这种情况下你可以,但我的应用程序中没有很多只有一个成员函数的类:-)
【解决方案2】:

你不需要 c++0x。在&lt;functional&gt; 你有bind1st bind2nd mem_funmem_fun_ref。您还有Boost.Bind,它概括了上述所有功能(IIRC)。

凭记忆...

vector<Foo> foo = makeVector();
vector<Foo*> foop = makeVectorP();
vector<Bar> bar1,bar2,bar3,bar4;
transform( foo.begin(), foo.end(), back_inserter( bar1 ), mem_fun_ref(&Foo::getBar) );
transform( foop.begin(), foop.end(), back_inserter( bar2 ), mem_fun(&Foo::getBar) );
transform( foo.begin(), foo.end(), back_inserter( bar3 ), bind1st(&bar_from_foo) );
transform( foo.begin(), foo.end(), back_inserter( bar4 ), boost::bind(&bar_from_foo, _1) );

【讨论】:

  • bind1st、bind2nd、mem_fun 和 mem_fun_ref 在 C++11 中已弃用。
【解决方案3】:

虽然std::function 工作得很好,但我想指出这段漂亮的委托代码,写成here(包括示例用法!)。按照那里的参考资料和答案,您可以阅读有关此 Delegate 类是如何构造的以及为什么它可能比 std::function 更快的所有信息。

还要注意我的问题here,我在 VS 2015 上遇到的问题。

【讨论】:

    【解决方案4】:

    您不一定需要等待 C++0x。您几乎可以在当前的 C++03 标准中实现委托。 您只需重载运算符 (),这样您就可以调用 MyObjectFunctor functor; functor(); 并且由于仿函数是一个对象,您可以将其作为委托/对象传递给函数;

    当前版本的 STL 定义了标头 &lt;algorithm&gt;,它提供了可与 Functors/Lambdas/Delegates 一起使用的函数。

    函子的简单示例。

    struct FunctorDelegate
    {
        // as so to delegate as a function that takes an int input
        void operator()(int) 
        {
            // do what I want
        }
    };
    
    int main()
    {
        //... do some stuffs with an std::vector<int> aRange; 
        FunctorDelegate functor;
        std::for_each(aRange.begin(), arange.end(), functor);
    }
    

    【讨论】:

    • 委托可以做的是将int A::func1(int, int)int B::func2(int, int)存储在一个变量中的能力(比如f),这样它就可以像int v = f(a, 12, 34);或@一样被调用987654328@。在您的示例中,可以调用仿函数,但不能将其视为函数类型 void(int) 的抽象。
    【解决方案5】:

    C 的机制一直都是函数指针&接力棒(除了 qsort() 和 bsearch() 不接接力棒)。

    所以人们总是将类对象作为接力棒传递。

    例如:

    class tp {
        public:
            tp() { n = 0; }
            void m(int z) { printf("%d is %d\n", n++, z++); }
            int n;
    };
    
    void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton)
    {
        for (int i = 0; i < cnt; i++)
            handler(opx[itm], baton);
    }
    
    /* You would need to provide this stub -- potentially templateable */
    void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); }
    
    /* used like so: */
    int main()
    {
        int array[7];
    
        //...
        tp cx;
        higher_func(array, 7, translate_baton, &cx);
    }
    

    【讨论】:

    • 这个问题与 C 无关:C 机制在 C++ 中可用,但这并不是最佳选择。
    • 我在 .NET 中与委托人做了大量工作,相信我这样可以省去委托人的麻烦,而不是相反。
    猜你喜欢
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 2012-09-06
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多