可以具有不同基成员实现的类的最佳实现
Posted
技术标签:
【中文标题】可以具有不同基成员实现的类的最佳实现【英文标题】:Best implementation for a class that can have different base member implementations 【发布时间】:2020-01-17 11:33:18 【问题描述】:我想要一个子类Handler
来处理多个回调并将数据从一个类传输到另一个类。但是,基类B1
和B2
可以对其成员有不同的实现。
下面是实现我想要的行为的方法。我认为应该有更好的方法,但无法弄清楚。
// 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
【问题讨论】:
您的IBase
类实现似乎泄漏了内存。我认为你把事情复杂化了。但老实说,我根本不明白你想要达到什么目的。
你能描述一下你想用这个设计解决什么问题吗?
简而言之:我想实现多种通信协议。 Handler
类实现所有协议所需的通用功能。但是B
和C
类的方法实现取决于协议的种类。基本上我想要一个像class Handler : public T
这样的类签名,其中T 可以是protocol1Handler 或protocol2Handler。但这种签名是不可能的。
这让我想起了策略设计模式,只是你同时有各种策略,必须选择正确的一个。
您需要运行时多态性吗?从您的示例中不清楚 - 请注意 Handler<B1>
和 Handler<B2>
是不同的类型。
【参考方案1】:
在 C++ 中有几种方法可以做到这一点。很难说最好的方法是什么,这取决于你将如何使用它,而且你给出的例子太简单了,无法推荐具体的方法。通常,我会说你想从Handler
派生你的协议特定类,而不是相反,所以你会写:
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
成员变量。
【讨论】:
感谢您的帮助。至于第一个例子。这也是我通常会如何实现它的方式。但是,我必须处理一些遗留代码。稍后我会看看我是否可以重写它仍然与旧代码兼容。至于第二个例子。在我的帖子之前,我也在尝试这个,但无法让它正确地用于向下和向上调用。我认为这是因为我的Handler
继承自B1
,因为它在当前代码中,而不是相反。我将测试这些想法并将其结合回来!以上是关于可以具有不同基成员实现的类的最佳实现的主要内容,如果未能解决你的问题,请参考以下文章