我正在更新接收多播消息的系统,将数据解析为类,然后通过 指向通过队列的单独线程的基类指针。然后另一个线程读取数据 从类中,将它们存储在表中。
我们收到两种不同类型的邮件。这是班级设计:
class BaseMsg
{
public:
BaseMsg(char tp) : msgType(tp) {}
virtual ~BaseMsg() = 0;
char msgType;
}
class MsgType1 : public BaseMsg
{
public:
MsgType1( int a, int b) : BaseMsg('1'), val1(a), val2(b) {}
virtual ~MsgType1();
int val1, val2;
}
class MsgType2 : public BaseMsg
{
public:
MsgType2( double a, double b) : BaseMsg('2'), val1(a), val2(b) {}
virtual ~MsgType2();
double val1, val2;
}
这是接收代码:
void reciveMessage( char *datablob, MsgQueue *queue)
{
BaseMsg *msgReceived;
char type = datablob[0]; // message type is the first character in the data,
// the rest of the blob varies based on that type
if ( type == '1' ) {
// code for parsing type 1 into 2 ints, i1, i2
msgReceived = new MsgType1( i1, i2);
} else {
// code for parsing type 2 into 2 doubles, d1, d2
msgReceived = new MsgType2( d1, d2);
}
queue->push(msgReceived);
}
这是在单独的线程中运行的流程代码:
void processMessage(MsgQueue *queue)
{
BaseMsg *msgToProcess = queue->pop();
if ( msgToProcess->msgType == '1' ) {
MsgType1 *mt1 = static_cast<MsgType1 *>(msgToProcess);
// do stuff with the message type 1 data
} else {
MsgType2 *mt2 = static_cast<MsgType2 *>(msgToProcess);
// do stuff with the message type 2 data
}
}
我知道检查消息类型然后向下转发是草率的,但考虑到沟通的限制 通过队列,我无法想出更好的解决方案。即使使用dynamic_cast&lt;&gt; (哪一个 我出于性能原因不想这样做会带来同样的问题;它仍然需要知道 将msgToProcess转换为什么类型的类。
关于如何摆脱支票的任何建议&amp;铸件?我有很多经验 与C&amp; C ++,但OO设计并不多,所以可能有一种我一无所知的方式。
另请注意,这是一个非常精简的示例来说明问题。那里 实际上超过50种不同的消息类型,性能至关重要,正如我们所能收到的那样 每秒数百万条消息。
答案 0 :(得分:3)
我同意其他建议使用多态性的固有属性并使用成员函数的人。
但我也理解保持消息类非常干净的必要性。我认为在这种情况下使用访问者模式(依赖于多态)可能是一个好主意:
class BaseMsg {
public:
virtual void accept(MsgProcessor& p) = 0;
};
class Msg1 : BaseMsg {
public:
void accept(MsgProcessor& p) { p.process(*this); }
};
class Msg2 : BaseMsg {
public:
void accept(MsgProcessor& p) { p.process(*this); }
};
class MsgProcessor {
public:
void process(Msg1& m);
void process(Msg2& m);
}
很酷的是,如果任何派生类缺少其中一个函数,则无法编译。
编辑:修复了评论中指出的内容
edit2:有两个代码库&amp;外部代码库中的最小变化:
外部代码库:
class MsgVisitor;
class BaseMsg {
public:
virtual void accept(MsgVisitor&) = 0;
};
class Msg1;
class Msg2;
class MsgVisitor {
public:
virtual void visit(Msg1&) = 0;
virtual void visit(Msg2&) = 0;
};
class Msg1 : public BaseMsg {
public:
void accept(MsgVisitor& v) { v.visit(*this); }
};
class Msg2 : public BaseMsg {
public:
void accept(MsgVisitor& v) { v.visit(*this); }
};
本地代码库:
class MsgProcessor : public MsgVisitor {
public:
void visit(Msg1& m) { ... } // do stuff for Msg1
void visit(Msg2& m) { ... }
};
void processMessage(MsgQueue *queue)
{
BaseMsg *msgToProcess = queue->pop();
msgToProcess->accept(MsgProcessor());
//delete msgToProcess;
}
答案 1 :(得分:2)
我会在类doStuff()
中定义一个名为BaseMsg
的纯虚函数。
每个派生类都实现该方法
在processMessage
内,您只需致电msgToProcess->doStuff()