c++ - 事件处理 : Sending events from base classes when the receiver expects derived classes

标签 c++

这段代码从本质上提炼了问题:

基础设施类:

struct EventReceiverBase {
    virtual ~EventReceiverBase() { }
};

template<typename T>
struct EventReceiver : public virtual EventReceiverBase {
    virtual void receiveEvent(T* pSender) = 0;
};

struct EventSender {
    EventReceiverBase* pReceiver;

    template<typename T>
    void sendEvent(T* pSender) {
        EventReceiver<T>* pCastedReceiver =
            dynamic_cast<EventReceiver<T>*>(pReceiver);
        // HERE IS THE PROBLEM
        // pCastedReceiver is null. T is BaseSender. The pointer
        // being casted is really of type EventReceiver<DerivedSender>*,
        // but it tries to cast to EventReceiver<BaseSender>*, and that
        // fails.
        pCastedReceiver->receiveEvent(pSender);
    }
};

用户类别:

struct BaseSender : public virtual EventSender {
    void f() {
        sendEvent(this);
    }
};
struct DerivedSender : public BaseSender { };

struct MyClass : public virtual EventReceiver<DerivedSender> {
    void receiveEvent(DerivedSender* pSender) { }
};

int main() {
    MyClass my;
    DerivedSender derivedSender;
    derivedSender.pReceiver = &my;
    derivedSender.f();
}

我可以改写这个问题(不是双关语)来避免这个问题吗?我想让用户类尽可能简单,同时尽可能以这种方式公开事件发送和接收功能。

例如,我也可以通过使 MyClass 派生自 EventReceiver 来“修复”它,但我真的很想避免这种情况,因为这意味着每个接收事件的类都需要额外的工作。

编辑:可执行粘贴:http://liveworkspace.org/code/4bm6OU $13

最佳答案

您看到问题的原因与 BaseSenderf 函数的放置有关:在对 sendEvent 的调用中下面,this 表示指向 BaseSender 的指针。本质上,下面的调用

void f() {
    sendEvent(this);
}

是一个简短的写法:

void f() {
    sendEvent<BaseSender>(this);
}

f 移动到 DerivedSender fixes this problem .

另一种方法是使 BaseSender::f 成为模板:

template <typename T>
void f() {
    sendEvent<T>((T*)this);
}

并这样调用它:

derivedSender.f<DerivedSender>();

这看起来不是特别好,但在现实世界 f 很大的情况下可能是代码复制粘贴的变通方法。

另一种解决方案是使 BaseSender 成为模板,如下所示:

template<typename T>
struct BaseSender : public virtual EventSender {
    void f() {
        sendEvent((T*)this);
    }
};
struct DerivedSender : public BaseSender<DerivedSender> {
};

这也有效(link to ideone)。

关于c++ - 事件处理 : Sending events from base classes when the receiver expects derived classes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14081637/

相关文章:

c++ - WNetAddConnection 不会失败但不起作用

c++ - 多线程代码 : vector<bool> iterators incompatible

c++ - 如何在 C++ 中使用 C 代码

c++ - QTabWidget - 如何分别编辑每个小部件?

java - Java 中除了字符串还有不可变对象(immutable对象)吗?

c++ - 使用 c/c++ 的文件 IO 技巧

c++ - 混合 fstream 和 stdio 有技术上的危险吗?

c++ - 无法使用 clang_complete 完成 qt

c++ - 尝试在 for 循环中使用 2 个列表迭代器

c++ - std::less<void> 和指针类型