使用未识别类型调用 class 的方法

Calling the method of class with unidentified type

我有一个名为 MyClass 的 class 已被另一个 class 订阅。当某些事件发生时,MyClass 应该通知订阅者。 我正在尝试使用订阅者类型的模板。因为我不想让其他人(负责订阅者class)需要关心修改MyClass来订阅。 所以我在下面写了代码,

class MyClass {

public:

    template<typename T>
    void subscribeEvents(const T &controller)
    {
        m_subscriber = static_cast<T*>(m_subscriber);
        m_subscriber = &controller;
    }

    void notifyPositionChanged(const long &position) const {

          (m_subscriber)->onPositionChanged(position);
    }

private:

    void m_subscriber;  // will be changed to array or something else

}

实际上 controller 对象有一个名为 onPositionChanged.

的方法

但是如您所知,它不是为这一行编译的。

(m_subscriber)->onPositionChanged(position);

现在我明白为什么会报错了,但问题是我不知道如何修改代码或更改我的设计。请让我知道我遗漏了什么和误解。提前致谢。

您需要为所有订阅者定义一个通用接口,然后将此接口用作m_subscriber 的类型。将您收到的任何参数野蛮地转换为已定义的类型只会导致未定义的行为。

您不需要为此使用模板。只需为您的订阅者使用基础 class。而 MyClass 在你的基础上运行 class

class ISubscribe {
public:
    virtual void onPositionChanged(const long &position) = 0;
};

class MyClass {
public:

    void subscribeEvents(ISubscribe *controller)
    {
        m_subscriber = controller;
    }

    void notifyPositionChanged(const long &position) const {

      (m_subscriber)->onPositionChanged(position);
    }
private:

    ISubscribe *m_subscriber;  // will be changed to array or something else
};

class SampleSubscriber : public ISubscribe {
public :
    void onPositionChanged(const long &position) override{
              ...
    }
};

void main() {
    SampleSubscriber s;
    MyClass m;

    m.subscribeEvents(&s);
 ....
}

使用std::function:

class MyClass {
public:

    template<typename CALLBACK>
    void subscribeEvents(CALLBACK &&controller)
    {
        m_subscriber = std::forward<CALLBACK>(controller);
    }

    void notifyPositionChanged(const long &position) const
    {
        if (m_subscriber)
            m_subscriber(position);
    }

private:
    std::function<void(const long&)> m_subscriber;
}

这使订阅者可以完全自由地选择想要订阅的内容。例如:

there.subscribeEvents([this](const long &pos) { handlePosChange(pos); }