C++ QT 在 class 结构中传递消息的最佳方式
C++ QT best way to pass a message higher in class structure
我目前正在实现一个程序,在QT中实现PC程序与外部设备的TCP通信。我遇到的问题比较笼统,但我会以这个为例。
我的 class 层次结构如下所示:
Program
/ \
Server_A <--> Server_B <--- External system
|
Sockets[]
/ \
Commands Confirmations
/ | \
Interf1 Interf2 Interf3
我可以从设备 (Socket
) 获取命令,我的命令进入 Confirmation
class,实现任何 Interface
作业,并且 returns确认返回给 Socket
,后者将其发送回设备。
当我想从外部系统发送命令时出现问题,我也必须确认。
- 我在
Server_B
上收到一条消息并将其传递给 Server_A
,其中包含以下信息:socket
发送命令和命令实现。
- 我将命令传递给特定的
socket
Socket
向 Commands
发送命令,因为存在外部系统命令的逻辑。
Commands
准备消息,运行逻辑,并(通过套接字)向设备发送消息
Socket
等待响应
Socket
获取响应,了解这是对外部系统命令的响应,并将其传递回 Commands
Commands
实现其逻辑。
到这里就可以了,但是下一步是:
Commands
需要向外部系统确认成功(或失败)。
所以基本上,我要做的就是通过这种方式将消息从 Commands
传递到 Server_B
:
Commands->Socket->Server_A->Server_B
。对于所有这些 classes,我将不得不创建一个不必要的方法来传递这个信息。有没有办法以某种方式解决这个问题?在我的编程过程中,经常发生我必须将某些东西传递到我的 class 结构的更高层,并且通过仅进一步传递信息的附加方法来实现它看起来是多余的。
我已经为这个问题提供了一个示例伪代码:
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)
最后,我想出了一个解决办法。有必要实施 ExternalCommand
class,这些实例是在 Server_B
.
中创建的
在极简解中,它有:1.字段QString Message
,2.方法QString getMessage()
,3.方法void finish(QString)
,4.信号void sendToExternal(QString)
当我在 Server_B
中读取从外部系统发送的消息时,我创建了这个 class 的实例,并将其连接到 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 模式,这对找到这个解决方案很有帮助。
我目前正在实现一个程序,在QT中实现PC程序与外部设备的TCP通信。我遇到的问题比较笼统,但我会以这个为例。
我的 class 层次结构如下所示:
Program
/ \
Server_A <--> Server_B <--- External system
|
Sockets[]
/ \
Commands Confirmations
/ | \
Interf1 Interf2 Interf3
我可以从设备 (Socket
) 获取命令,我的命令进入 Confirmation
class,实现任何 Interface
作业,并且 returns确认返回给 Socket
,后者将其发送回设备。
当我想从外部系统发送命令时出现问题,我也必须确认。
- 我在
Server_B
上收到一条消息并将其传递给Server_A
,其中包含以下信息:socket
发送命令和命令实现。 - 我将命令传递给特定的
socket
Socket
向Commands
发送命令,因为存在外部系统命令的逻辑。Commands
准备消息,运行逻辑,并(通过套接字)向设备发送消息Socket
等待响应Socket
获取响应,了解这是对外部系统命令的响应,并将其传递回Commands
Commands
实现其逻辑。
到这里就可以了,但是下一步是:
Commands
需要向外部系统确认成功(或失败)。
所以基本上,我要做的就是通过这种方式将消息从 Commands
传递到 Server_B
:
Commands->Socket->Server_A->Server_B
。对于所有这些 classes,我将不得不创建一个不必要的方法来传递这个信息。有没有办法以某种方式解决这个问题?在我的编程过程中,经常发生我必须将某些东西传递到我的 class 结构的更高层,并且通过仅进一步传递信息的附加方法来实现它看起来是多余的。
我已经为这个问题提供了一个示例伪代码:
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)
最后,我想出了一个解决办法。有必要实施 ExternalCommand
class,这些实例是在 Server_B
.
在极简解中,它有:1.字段QString Message
,2.方法QString getMessage()
,3.方法void finish(QString)
,4.信号void sendToExternal(QString)
当我在 Server_B
中读取从外部系统发送的消息时,我创建了这个 class 的实例,并将其连接到 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 模式,这对找到这个解决方案很有帮助。