C++ QT 在类结构中传递更高消息的最佳方法
Posted
技术标签:
【中文标题】C++ QT 在类结构中传递更高消息的最佳方法【英文标题】:C++ QT best way to pass a message higher in class structure 【发布时间】:2021-08-18 09:23:33 【问题描述】:我目前正在实现一个程序,在QT中实现PC程序与外部设备之间的TCP通信。我遇到的问题比较笼统,但我会以这个为例。
我的类层次结构如下所示:
Program
/ \
Server_A <--> Server_B <--- External system
|
Sockets[]
/ \
Commands Confirmations
/ | \
Interf1 Interf2 Interf3
我可以从设备(Socket
)获取命令,我的命令进入Confirmation
类,实现任何Interface
作业,并将确认返回给Socket
,后者将其发送回设备。
当我想从外部系统发送命令时会出现问题,我也必须确认。
-
我在
Server_B
上收到一条消息并将其传递给Server_A
,其中包含以下信息:socket
发送命令和命令实现。
我将命令传递给特定的socket
Socket
向Commands
发送命令,因为存在外部系统命令的逻辑。
Commands
准备消息,运行逻辑,并(通过套接字)向设备发送消息
Socket
等待回复
Socket
得到响应,知道它是对外部系统命令的响应,并将其传回给Commands
Commands
实现了它的逻辑。
这里一切都会好的,但下一步是:
Commands
需要向外部系统确认成功(或失败)。
所以基本上,我要做的就是通过这种方式将消息从Commands
传递给Server_B
:
Commands->Socket->Server_A->Server_B
。对于所有这些类,我必须创建一个不必要的方法来传递这一信息。有没有办法以某种方式解决这个问题?在我的编程过程中,经常需要将一些东西传递给我的类结构的更高层,而通过仅进一步传递信息的附加方法来实现它似乎是多余的。
我已经为这个问题提供了一个示例伪代码:
class Program
ServerB serverB;
ServerA serverA;
class ServerB
void send(QString msg);
class ServerA
QVector<MySocket*> sockets;
class MySocket
Commands commands;
Confirmations confirmations;
class Commands
void doLogic();
void sendToExternalSystem(QString message); //How to realize it?
我的程序要大得多,但我希望它能让您了解我想要实现的目标。最简单的解决方案是在 Sockets、Server_A 和 Server_B 中添加一个方法 void sendToExternalSystem(QString message)
,并在构造期间为每个父级提供一个指针(命令将有权访问套接字,套接字将有权访问 server_a,而 server_a 将有权访问server_b)
【问题讨论】:
为什么看起来“可怕”?为什么你认为做一些有用的方法是“不必要的”?你能发布一个小例子来说明这个问题吗?要求避免某些代码而不显示代码是困难的 我使用了“冗余”这个词 :),我提供了简单的伪代码,希望对您有所帮助,但这是我的问题 - 如果 Server_B 是一个全局类,它会很简单(只需运行 Server_B .send(message)),但事实并非如此,我必须通过 4 个不同的对象传递sendToExternalSystem(QString message)
,我希望我能在保持高质量代码的同时以某种方式解决它,我的问题的重点是我想学习一个解决此类问题的技术,因为它对我来说经常发生,我相信仅仅因为这种情况可能不是最好的解决方案而保存父指针。
答案类型:it is actually the best solution to provide pointers to parent and new methods
就可以了。至于现在,我只是有一种感觉,我这样做会做错事,可以做得更好的事情。
当某物委托其他实体执行会产生结果的任务时,您可以考虑承诺/未来模式
@MatG 我刚刚检查了承诺/未来模式,它看起来是一个很好的解决方案。如果我错了,你能纠正我吗?这是否意味着我必须用消息传递一个承诺,一旦我想重新发送确认,用消息填充它,然后调用完成,在 Server_B 上使用观察者它会产生一个信号,我会能应付吗?我也打算在单线程应用程序上使用它,但我相信这不是观察者信号的问题。
【参考方案1】:
最后,我想出了一个解决方案。必须实现ExternalCommand
类,这些实例是在Server_B
中创建的。
在最小解决方案中,它有:1.字段QString Message
,2.方法QString getMessage()
,3.方法void finish(QString)
,4.信号void sendToExternal(QString)
当我在Server_B
中读取外部系统发送的消息时,我创建了该类的一个实例,并将其连接到Server_B
发送方法。在我的代码中,它看起来像这样:
ExternalCommand::ExternalCommand(QString message, QObject* parent) : QObject(parent)
this->message=message;
QString ExternalCommand::getMessage()
return this->message;
void finish(QString outputMessage)
emit sendToExternal(outputMessage);
void Server_B::onReadyRead()
QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
QString message = socket->readAll();
ExternalCommand* cmd = new ExternalCommand(message);
connect(cmd, &ExternalCommand::sendToExternal, socket,
[socket](QString message) socket->write(message.toUtf8()););
还需要在发送命令后在ExternalCommand
中实现某种类型的对象销毁,但这不是这个问题的重点。
所以一旦这个实现,而不是QString
的消息,消息会以ExternalCommand*
的形式传递给较低的级别,一旦得到答案,就可以将其发送回外部系统,致电ExternalCommand::finish(QString outputMessage);
。当然,这只是这个问题的最小解决方案。
感谢 @MatG 向我指出 Promise/Future 模式,这有助于找到此解决方案。
【讨论】:
以上是关于C++ QT 在类结构中传递更高消息的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章