[C++] 信号

前言

信号与槽是QT的一个概念,原版C++里并没有

使用

先声明一些类
Receiver负责接收信号,Emitter2则是负责发送

class Receiver : public ntl::Reflectible
{
public:
    void received(int num)
    {
        std::cout << "received:" << num << std::endl;
    }
};

class Emitter2 : public ntl::Signalable
{
public:
    Emitter2()
    {
        m_signals.insert(
            ntl::Signalable::SignalMap::value_type(
                "signal",
                ntl::Signal(1)));
    }

public:
    void emit_signal()
    {
        emit("signal", 123);
    }
};

接着连接信号
说明一下信号的名称、接收对象与方法

emitter2.connect("signal", "receiver", &receiver, &Receiver::received);

最后发送信号

emitter2.emit_signal();

没错的话应该输出以下字符

received:123

说明Receiver成功接收到了Emitter2发出的信号

代码

此物需要借助上篇文章的力量
并位于github之中,尔等可观赏其细节

Slot

Slot需要与对象绑定
用void*说明对象的位置
NonStaticMethod如其名,是一个用于调用的非静态方法

	/// @brief 槽
    class NTL_ALIGN Slot : public BasicObject
    {
    public:
        using SelfType = Slot;
        using ParentType = BasicObject;

    protected:
        /// @brief 槽的对象
        void *m_object = nullptr;

        /// @brief 方法
        NonStaticMethod m_method;

    public:
        Slot() = default;
        explicit Slot(void *object, const NonStaticMethod &method);
        explicit Slot(const SelfType &from) = default;
        ~Slot() = default;

    public:
        SelfType &operator=(const SelfType &from) = default;

    public:
        void *get_object() const;
        const NonStaticMethod &get_method() const;

    public:
        template <typename... ArgsType>
        void received(ArgsType &&...args) const;
    };

Signal

Signal可以连接多个Slot,并允许删改

	/// @brief 信号
    class NTL_ALIGN Signal : public BasicObject
    {
    public:
        using SelfType = Signal;
        using ParentType = BasicObject;

        /// @brief 槽容器
        using SlotContainer = std::map<String, Slot>;

    protected:
        /// @brief 槽
        SlotContainer m_slots;

        /// @brief 参数总数
        SizeT m_args_count = 0;

    public:
        Signal() = default;
        explicit Signal(SizeT args_count);
        explicit Signal(const SelfType &from) = default;
        ~Signal() = default;

    public:
        SelfType &operator=(const SelfType &from) = default;

    public:
        const SlotContainer &get_slots() const;
        SizeT get_args_count() const;

        bool has_slot(const String &name) const;

    public:
        template <typename MethodType>
        void connect(const String &name, void *object, MethodType method);
        void connect(const String &name, const Slot &slot);

        void disconnect(const String &name);

        template <typename... ArgsType>
        void emit(ArgsType &&...args) const;
    };

Signalable

Signalable是一个可以发送/接收信号的对象,继承自Reflectible

	/// @brief 可发送/接收信号的对象
    class NTL_ALIGN Signalable : public Reflectible
    {
    public:
        using SelfType = Signalable;
        using ParentType = Reflectible;

        /// @brief 信号列表
        using SignalMap = std::map<String, Signal>;

    protected:
        /// @brief 信号列表
        SignalMap m_signals;

    public:
        Signalable() = default;
        explicit Signalable(const SelfType &from) = default;
        ~Signalable() = default;

    public:
        SelfType &operator=(const SelfType &from) = default;

    public:
        const SignalMap &get_signals() const;

        bool has_signal(const String &signal) const;

    public:
        template <typename MethodType>
        void connect(const String &signal, const String &name, void *object, MethodType method);
        void connect(const String &signal, const String &name, const Slot &slot);

        void disconnect(const String &signal, const String &name);

        template <typename... ArgsType>
        void emit(const String &signal, ArgsType &&...args) const;

    public:
        static OutOfRangeException unable_to_find_signal(const String &signal, const String &where);
    };

你可能感兴趣的:(笔记,c++,信号,信号与槽)