2

我希望能够在 C++ 中使用类似 Java 的接口语义。起初,我曾经boost::signal为给定的事件回调显式注册的成员函数。这非常有效。

但后来我决定一些函数回调池是相关的,将它们抽象并立即注册所有实例的相关回调是有意义的。但我了解到的是,boost::bind和/或取值的特定性质this似乎打破了这一点。或者也许只是add_listener(X &x)方法声明改变了boost::bind生成的代码的事实。

我对问题发生的原因有一个非常粗略的理解,我认为它可能按照其设计正常运行。我很好奇:我应该怎么做呢?当然有一个正确的方法来做到这一点。

这是一些示例代码:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

using namespace std;

struct X;
struct Callback
{
    virtual void add_listener(X &x) = 0;
};

struct X
{
    X() {}
    X(Callback &c) {  c.add_listener(*this); }
    virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};

struct CallbackReal : public Callback
{
    virtual void add_listener(X &x)
    {
        f = boost::bind<void>(boost::mem_fn(&X::go), x);
    }

    void go() { f(); }

    boost::function<void (void)> f;
};


struct Y : public X
{
    Y() {}

    Y(Callback &c) {  c.add_listener(*this); }
    virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};


int main(void)
{
    CallbackReal c_x;
    CallbackReal c_y;

    X x(c_x);
    Y y(c_y);

    cout << "Should be 'X'" << endl;
    boost::bind<void>(boost::mem_fn(&X::go), x)();

    cout << "Should be 'Y'" << endl;
    boost::bind<void>(boost::mem_fn(&X::go), y)();

    cout << "------------------" << endl;

    cout << "Should be 'X'" << endl;
    c_x.go();
    cout << "I wish it were 'Y'" << endl;
    c_y.go();

    return 0;
}

好吧,我没有完全描述这个问题。标题具有误导性。

天啊。否决这个。我显然没有很好地描述这个问题,我认为这最终归结为主要是一个语法错误。:(

4

2 回答 2

3

boost::bind按值获取其参数并复制它们。这意味着

f = boost::bind<void>(boost::mem_fn(&X::go), x);

将传递 的副本x它将切掉它的Y一部分(如果它真的是 aY开始的话)。要使虚拟调度工作,您需要将指针传递给boost::bind

f = boost::bind(&X::go, &x);

(请注意,您实际上并不需要mem_fn或显式编写<void>,因为boost::bind参数推导会为您处理这些问题。)

于 2010-10-27T22:51:28.090 回答
0

Java 接口并不专门存在于 C++ 中。最接近的是纯抽象基类。这通常足够接近。

您的其余问题与接口无关。Java 使用观察者模式进行事件连接和分派。接口部分只是轻微相关,因为观察者需要遵守特定的接口(当然,否则你不会知道要调用什么)。

使用 boost::bind 创建函子实际上是一种超越接口的抽象,因此是一种更通用的解决方案。观察者模式和仿函数被放在各种库中实现的信号/槽习惯用法/模式中,例如 boost::signals、boost::signals2 和 gtk++。Qt 版本在机制上完全不同,但在概念上相似。

那么,这意味着什么可以帮助您了解什么、为什么以及在哪里?我建议从搜索什么是观察者模式开始,然后尝试编写一些实现。

于 2010-10-27T23:24:31.197 回答