gpt4 book ai didi

c++ - 避免静态和动态转换

转载 作者:搜寻专家 更新时间:2023-10-31 00:28:46 26 4
gpt4 key购买 nike

我正在更新一个接收多播消息的系统,将数据解析为类,然后通过通过队列指向单独线程的基类指针。然后另一个线程读取数据来自类,并将它们存储在表中。

我们收到两种不同的消息。这是类设计:

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<>(出于性能原因我不想这样做)会带来同样的问题;它仍然需要知道将 msgToProcess 转换成什么类型​​的类。

关于如何摆脱检查和转换的任何建议?我有很多经验使用 C 和 C++,但对 OO 设计了解不多,所以可能有一种方法我一无所知。

另请注意,这是一个非常精简的示例来说明问题。那里实际上有超过 50 种不同的消息类型,性能很关键,因为我们可以接收每秒数百万条消息。

最佳答案

我同意其他人建议使用多态性的固有属性并使用成员函数。

但我也理解保持消息类非常干净的必要性。我认为在这种情况下使用访问者模式(依赖于多态性)可能是个好主意:

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:有两个代码库和外部代码库的最小变化:

外部代码库:

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;
}

关于c++ - 避免静态和动态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43857926/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com