线程消息或更好:访问“大师班”中其他班级的成员

Posted

技术标签:

【中文标题】线程消息或更好:访问“大师班”中其他班级的成员【英文标题】:Thread messaging or better: Accessing members from other class in "master-class" 【发布时间】:2020-01-24 22:16:53 【问题描述】:

首先:对不起,可能是错误的标题和这么多的文字 - 这是因为我试图尽可能准确地描述我的问题! :)

如果我的主要想法不清楚,请添加评论 - 我会尝试重写问题(因为英语不是我的母语)。

如果有更好的方法可以做到这一点,我也很高兴您能与我分享您的想法!

背景

我目前正在使用 C++ 开发一个消息传递系统,用于线程之间的交互。 主要思想是创建一个类——我们称它们为SharedMessage,它保存着我的消息数据。分配值后,我想将它们添加到队列中,以便我的线程可以处理存储在这些消息中的信息。

问题在于,消息的内容取决于其类型。例如。有多种“消息类型”,但所有这些不同的类型都应保存在同一个队列中(例如messages)。


第一个/最简单的想法

我想到的最简单的方法就是将一个列表 args_string_ 作为成员变量添加到我的 SharedMessage-class 并使用 getter 和 setter 访问列表的内容。为了区分不同的消息类型,我使用了另一个名为 messageType 的成员变量。 这是一个例子:

class SharedMessage
public: 
  void setMessageType(int type)(); // sets the message type
  void addArg(std::string arg)(); // add an item to the list
  void getArgs(); // Should return the list args_string_
private:
 int messageType = 1;
 std::vector<string> args_string_;
;

现在我只是填充我的班级列表,分配一个 messageType,然后将它们添加到我的队列中。我的线程可以从我的队列(队列messages)中访问和删除它们。

问题:这不是一个非常优雅的方式。我总是需要知道我的论点需要按什么顺序处理。


我的假设:

由于上述问题,我更多地考虑使用模板继承之类的东西。我不知道是否有类似的东西 - e。 G。从其他类动态继承。

让我们看看我的想法:

在这种情况下,我再次获得了SharedMessage-class——但现在我没有添加任何成员。这是因为我想稍后在运行时/实例化/编译时定义成员(这甚至可能吗?)——可能与 STL-Class 执行此操作的方式相同。

// This should be my "master"-class. The queue should be able to hold elements of this type.
class SharedMessage 
 ; 

现在我得到了两个“虚拟”命令:Command1Command2

// This is one possible command that can hold a string ("command1")
// They can be accessed by using getters/setters
class Command1
  std::string command1;
  void setCommand1(std::string cmd1);
  std::string getCommand1();


// Second possible command. Note that in this case my command holds an integer ("counter")
class Command2
  double counter;
  void setCounter(int cnt);
  int getCounter();

这些命令有不同的成员。 这个想法现在使用类似于以下代码的东西。在我的main 中,我创建了提到的队列messages,它可以保存SharedMessage 类型的实例。 现在这就是有趣的地方。我希望能够做这样的事情。建立一个SharedMessage,但使用来自Command1继承成员(可能类似于SharedMessage&lt;Command1&gt; sharedmessage;?) 之后我可以使用来自Command1 的这些成员,除了sharedmessage 的类型是SharedMessage

(这就是我想要访问成员的方式?!) 例如:

main() 
// This is my queue.
queue <SharedMessage> messages; 

// I want to create a Shared message of type Command1
SharedMessage<Command1> sharedmessage;

// This is the interesting line. Is there a function for this dynamic "member generation". Like inheritance (but in a dynamic way/like templates)?
sharedmessage.setCommand1("My command); // I’m using Command1 member beside “sharedmessage” is of datatype “SharedMessage”
// Add to queue
messages.push(sharedmessage);

// And this should also work :
SharedMessage<Command2> sharedmessage2;
message.setCounter(172);
// Add second message with different content to queue
messages.push(sharedmessage);


【问题讨论】:

【参考方案1】:

如果您使队列存储指向消息的指针,则可以使用继承。它看起来像这样:

class SharedMessage ...;
class Command1: public SharedMessage ...;
class Command2: public SharedMessage ...;
...
std::queue<SharedMessage *> messages;
Command1 message1;
Command2 message2;
messages.push(&message1);
messages.push(&message2);

缺点是您的队列现在不再存储消息本身,只是指针,因此您需要一些方法来管理它们的生命周期。一种可能是使用std::queue&lt;std::unique_ptr&lt;SharedMessage&gt;&gt;,并将消息添加到队列中,如下所示:

messages.push(std::make_unique<Command1>());
// or:
auto message2 = std::make_unique<Command2>();
messages.push(std::move(message2));

要从队列中取出消息,请编写如下内容:

std::unique_ptr<SharedMessage> message = std::move(messages.front());
messages.pop();

你不能像上一个例子那样使用模板,因为如果你有template&lt;typename T&gt; class SharedMessage ...,那么std::queue&lt;SharedMessage&gt; 不会编译,因为单独的SharedMessage 不是真正的类型。你可以创建一个std::queue&lt;SharedMessage&lt;Command1&gt;&gt;,但是当然你不能用它来存储一个SharedMessage&lt;Command2&gt;

【讨论】:

我也想过你指出的想法(我之前什至实现过)但我没有使用unique_ptr。由于没有其他选择,我会尝试实现使用unique_ptr的想法。

以上是关于线程消息或更好:访问“大师班”中其他班级的成员的主要内容,如果未能解决你的问题,请参考以下文章

类的公共成员及其访问

访问另一个班级中的一个班级成员[关闭]

访问修饰符

访问修饰符,命名空间

C#访问修饰符

多线程访问全局变量和局部变量