簡體   English   中英

繼承和模板,一種奇怪的行為

[英]Inheritance and templates, a weird behaviour

我現在試圖開發一個基於事件的狀態機幾個小時,但是我無法確定為什么下面的模板類不匹配。 基本上, State發布事件, StateMachine監聽事件。 這是一個片段:

#include <iostream>
#include <vector>

// Interface for event listening
template <typename Event, typename Sender>
class EventListener
{
public:
    virtual ~EventListener() = default;
    virtual void onEvent(const Sender* sender, const Event& data) = 0;
};

// Abstract class for event publishing
template <typename Event>
class EventPublisher
{
public:
    typedef EventListener<Event, EventPublisher> Listener;
    virtual ~EventPublisher() = default;

    // Queues an event listener
    void attach(Listener* listener) {
        listeners.push_back(listener);
    }

protected:
    // Publishes an event among all registered listeners
    void publish(const Event& e) {
        for (Listener* listener : listeners) {
            listener->onEvent(this, e);
        }
    }

private:
    std::vector<Listener*> listeners;
};

// Concrete publisher & listener
class StateEvent {};
class StateEventPublisher : public EventPublisher<StateEvent> {};
class StateEventListener : public EventListener<StateEvent, StateEventPublisher> {};

class State : public StateEventPublisher {
public:
    void foo() {
        publish(StateEvent());
    }
};

class StateMachine final : public StateEventListener {
private:
    void onEvent(const StateEventPublisher* sender, const StateEvent& e) override {}
};

int main()
{
    State state;
    StateMachine machine; // Is a StateEventListener, which is a EventListener<StateEvent, StateEventPublisher>, whereas StateEventPublisher is a EventPublisher<StateEvent>

    state.attach(&machine); // Incompatible with EventListener<StateEvent, EventPublisher<StateEvent>>*
    state.foo();

    return 0;
}

如果計算機是StateEventListener ,它是EventListener<StateEvent, StateEventPublisher> ,而StateEventPublisherEventPublisher<StateEvent> ,為什么不能將計算機附加到狀態? 我究竟做錯了什么?!

EventPublisher<StateEvent>聲明中, EventPublisher期望偵聽器為EventListener<StateEvent, EventPublisher<StateEvent>>而您提供的偵聽器為EventListener<StateEvent, StateEventPublisher> ,這是無關的類型(即使StateEventPublisher繼承自EventPublisher<StateEvent> )。

可能有幾種解決方法,例如使用CRTP:

// Interface for event listening
template <typename Event, typename Sender>
class EventListener
{
public:
    virtual ~EventListener() = default;
    virtual void onEvent(const Sender* sender, const Event& data) = 0;
};

// Abstract class for event publishing
template <typename Event, typename Sender>
class EventPublisher
{
public:
    typedef EventListener<Event, Sender> Listener;
    virtual ~EventPublisher() = default;

    // Queues an event listener
    void attach(Listener* listener) {
        listeners.push_back(listener);
    }

protected:
    // Publishes an event among all registered listeners
    void publish(const Event& e) {
        for (Listener* listener : listeners) {
            listener->onEvent(static_cast<Sender *>(this), e);
        }
    }

private:
    std::vector<Listener*> listeners;
};

// Concrete publisher & listener
class StateEvent {};
class StateEventPublisher : public EventPublisher<StateEvent, StateEventPublisher> {};
class StateEventListener : public EventListener<StateEvent, StateEventPublisher> {};

class State : public StateEventPublisher {
public:
    void foo() {
        publish(StateEvent());
    }
};

class StateMachine final : public StateEventListener {
private:
    void onEvent(const StateEventPublisher* sender, const StateEvent& e) override {}
};

int main()
{
    State state;
    StateMachine machine; // Is a StateEventListener, which is a EventListener<StateEvent, StateEventPublisher>, whereas StateEventPublisher is a EventPublisher<StateEvent>

    state.attach(&machine); // Incompatible with EventListener<StateEvent, EventPublisher<StateEvent>>*
    state.foo();

    return 0;
}

在線編譯器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM