c++ - 可以具有不同基成员实现的类的最佳实现

标签 c++ c++11 c++17

我想要一个 child 类Handler它处理多个回调并将数据从一个类传输到另一个类。但是,基类 B1B2它的成员可以有不同的实现。

下面是实现我想要的行为的方法。我认为应该有更好的方法,但无法弄清楚。

// Example program
#include <iostream>
#include <string>

template <class T>
class IBase
{
    public:
        IBase()
        {
            object = new T(*this);    
        };

        ~IBase()
        {
            delete object;
        }

        virtual void ValidateCallback()
        {
        };

        void RxCallback()
        {
           object->RxCallback();
        };

        void Send()
        {
            object->Send();
        };

       T* object;
};

class C1
{
    public:
        virtual void RxCompleteCallback() = 0;

        void RxParse()
        {
            std::cout << "Parse C1" << std::endl;
            RxCompleteCallback();
        };
};

class C2
{
    public:
        virtual void RxCompleteCallback() = 0;

        void RxParse()
        {
            std::cout << "Parse C2" << std::endl;
            RxCompleteCallback();
        };
};

class B1 : public C1
{
    public:
        B1(IBase<B1> &handler )
        {
           ihandler = &handler;
        };

        void DoSomething()
        {
            std::cout << "DoSomething B1" << std::endl;
            ihandler->ValidateCallback();
        };

        void RxCompleteCallback() override
        {
            std::cout << "DoSomething other than B2" << std::endl;
            std::cout << "RxCompleteCallback" << std::endl;
        };

        void RxCallback()
        {
            RxParse();
        };

        void Send()
        {
            DoSomething();
        };

        IBase<B1> * ihandler;
};

class B2 : public C2
{
    public:
        B2(IBase<B2> &handler )
        {
           ihandler = &handler;
        };

        void DoSomething()
        {
            std::cout << "DoSomething B2" << std::endl;
            ihandler->ValidateCallback();
        };

        void RxCompleteCallback() override
        {
            std::cout << "DoSomething other than B1" << std::endl;
            std::cout << "RxCompleteCallback" << std::endl;
        };

        void RxCallback()
        {
            RxParse();
        };

        void Send()
        {
            DoSomething();
        };

        IBase<B2> * ihandler;
};

class Validate
{
    public:
        void CalculateValidation()
        {
            std::cout << "Calculate validation" << std::endl;
        };
};

template <class T>
class Handler : public IBase<T>, public Validate
{
    public:
        void ValidateCallback() override
        {
            std::cout << "ValidateCallback" << std::endl;
            CalculateValidation();
        };

        void Receive()
        {
            IBase<T>::RxCallback();
        };

        void Send()
        {
           IBase<T>::Send();
        }

};

int main()
{
    Handler<B1> handler1;
    handler1.Receive();
    handler1.Send();
    std::cout << std::endl;
    Handler<B2> handler2;
    handler2.Receive();
    handler2.Send();
}

输出:
Parse C1
DoSomething other than B2
RxCompleteCallback
DoSomething B1
ValidateCallback
Calculate validation

Parse C2
DoSomething other than B1
RxCompleteCallback
DoSomething B2
ValidateCallback
Calculate validation

最佳答案

在 C++ 中有几种方法可以做到这一点。很难说最好的方法是什么,这取决于你将如何使用它,而且你给出的例子太简单了,无法推荐具体的方法。通常,我会说您想从 Handler 派生特定于协议(protocol)的类。 ,而不是相反,所以你会写:

class Handler {
public:
    virtual void Receive() {};
    virtual void Send() {};
};

class B1: public Handler {
    virtual void Receive() {
        ...
    }

    virtual void Send() {
        ...
    }
};

int main() {
    B1 handler1;
    handler1.Receive();
    ...
}

这里的主要问题是您需要使用 virtual成员函数在这里,否则基类不知道要调用哪个派生类的实现。但它确实允许您通过 Handler *作为另一个函数的参数,然后它将与任何派生类一起使用,而无需任何模板。

另一种选择是使用 curiously recurring template pattern ,看起来像:
template <typename T>
class Handler {
    void Receive() {
        static_cast<T*>(this)->Receive();
    }

    void Send() {
        static_cast<T*>(this)->Send();
    }
};

class B1: public Handler<B1>
{
    void Receive() {
        ...
    }

    void Send() {
        ...
    }
};

int main() {
    B1 handler1;
    handler1.Receive();
    ...
}

这避免了虚拟方法。
它也与您的class Handler 非常相似。 , 但它的优点是不需要 T *object成员变量。

关于c++ - 可以具有不同基成员实现的类的最佳实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59786563/

相关文章:

c++ - std::unordered_map::emplace 问题与私有(private)/删除的复制构造函数

c++ - 如何将对象 move 到未初始化的内存中?

C++17 检查有效表达式

c++ - 我如何找出下一个 C++ 的特定建议/论文的状态?

c++ - 如何防范内存泄漏?

c++ - GLFW3 不与 MinGW 合作

c++ - 有没有办法在不知道 c++ 中的大小的情况下迭代枚举

C++11 char 数组初始化和字符串文字

c++ - 什么是自动括号列表语法?

c++ - 使用 range-v3 读取逗号分隔的数字列表