问题 在C ++ 11中委派


C ++ 11是否提供代理?

如果没有,在C ++中做类似事情的最佳(最有效)方法是什么? Boost.Signals? FastDelegate?别的什么?


2593
2017-09-01 22:49


起源

函数指针有什么问题? - alternative
我不能用类方法使用它:/ - dot222
是的你可以 parashift.com/c++-faq-lite/pointers-to-members.html 但是可能有更好的东西要用,例如C ++函数不需要是方法,或者您可以将类转换为仿函数 - jk.


答案:


你可以使用类似委托的语义 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 到实例 C 命名 obj。这为我们提供了一个可以用单个调用的对象 int 参数和返回 void

我们称之为 Bar() 用这个对象和 Bar() 打电话 obj.Foo(42)


14
2017-09-01 23:03



+1,或者你可以把C变成一个仿函数。 - jk.
@jk:有时候。显然在这种情况下你可以,但我的应用程序中没有很多只有一个成员函数的类:-) - James McNellis


你不需要c ++ 0x。在 <functional> 你有 bind1st  bind2nd  mem_fun 和 mem_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) );

2
2017-09-02 13:00



在C ++ 11中不推荐使用bind1st,bind2nd,mem_fun和mem_fun_ref。 - Kay Sarraute


虽然 std::function 很好地工作,我想指出这段代码很好的代码 这里 (包括示例用法!)。根据参考和答案,你可以阅读所有这些 Delegate 构造了类,为什么它可能比它更快 std::function

还请注意我的问题 这里 对于我在VS 2015上遇到的问题。


1
2018-03-14 13:38





您不一定需要等待C ++ 0x。您可以在当前的C ++ 03标准中实现Delegates。 你只需要重载operator(),就可以调用 MyObjectFunctor functor; functor(); 由于函子是一个对象,你可以将它作为委托/对象传递给函数;

STL的当前版本定义了标头 <algorithm> 它提供了可以与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);
}

0
2017-09-02 11:33



代表们可以做的是存储的能力,例如, int A::func1(int, int) 要么 int B::func2(int, int) 在一个变量(比如说 f),所以它可以被称为 int v = f(a, 12, 34); 要么 int v2 = f(b, 42, 24);。在您的示例中,可以调用仿函数,但不能将其视为函数类型的抽象 void(int)。 - Siu Ching Pong -Asuka Kenji-


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);
}

-1
2017-09-01 23:17



这个问题与C无关:C机制在C ++中可用,但这并不是最佳选择。 - Steve Jessop
我在.NET中与代表们做了很多工作,相信我这样可以让我在代理方式上遇到麻烦,而不是相反。 - Joshua