Поток сообщений или лучше: доступ к членам из другого класса в «мастер-классе» - PullRequest
1 голос
/ 25 января 2020
  • Прежде всего: извините за, возможно, неверный заголовок и столько текста - это потому, что я пытаюсь описать мою проблему как можно точнее! :)

    • Если моя основная идея неясна, пожалуйста, добавьте комментарий - я постараюсь переписать вопрос (поскольку Engli sh не является языком моей матери).

    • Если есть еще лучший способ сделать это, я также был бы рад, если бы вы поделились со мной своими идеями!

Фон

В настоящее время я работаю над системой обмена сообщениями в C ++ для взаимодействия между потоками. Основная идея состоит в том, чтобы иметь класс - давайте назовем их SharedMessage, которые содержат мои данные сообщения. После назначения значений я хочу добавить их в очередь, чтобы мои потоки могли работать с информацией, хранящейся в этих сообщениях.

Проблема в том, что содержание сообщений зависит от его типа. Например Есть несколько «типов сообщений», но все эти различные типы должны храниться в одной и той же очереди (например, messages).


Первая / Простейшая идея

Самым простым подходом, о котором я думал, было просто добавить список args_string_ в качестве переменной-члена к моему SharedMessage -классу и получить доступ к содержимому списка с помощью getter и setter. Чтобы различать guish между различными типами сообщений, я использовал другую переменную-член под названием 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).

Проблема: это не очень элегантный способ. Мне всегда нужно знать, в каком порядке нужно обрабатывать мои аргументы.


Моя гипотетическая идея:

Из-за описанной выше проблемы я был более думать о чем-то вроде использования шаблонов или наследований . Я не знаю, есть ли что-то подобное - например, динамически наследовать от других классов.

Давайте посмотрим на мои идеи, о которых я думал:

В этом случае я снова получил свой SharedMessage -класс - но теперь я не добавляю никаких участников. Это потому, что я хочу определить элементы позже во время выполнения / создания экземпляра / компиляции (это вообще возможно?) - возможно, так же, как это делает класс STL.

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

Теперь я получил две «фиктивные» команды: Command1, Command2

// 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 . И вот теперь это становится интересным. Я хочу быть в состоянии сделать что-то подобное. Instciate SharedMessage, но с унаследованными членами от Command1 (может быть, что-то вроде SharedMessage<Command1> sharedmessage;?). Впоследствии я могу использовать эти члены из Command1, кроме того, sharedmessage имеет тип SharedMessage !

(Вот как я хочу получить доступ к участникам?!) E. g.:

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 Ответ

1 голос
/ 25 января 2020

Вы можете использовать наследование, если в своей очереди храните указатели на сообщения. Это выглядело бы так:

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<std::unique_ptr<SharedMessage>> и добавлять сообщения в очередь следующим образом:

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<typename T> class SharedMessage {...}, то std::queue<SharedMessage> не компилируется, так как один SharedMessage не является реальным типом. Вы можете сделать std::queue<SharedMessage<Command1>>, но, конечно, вы не сможете использовать его для хранения SharedMessage<Command2> in.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...