【问题标题】:Is it a bad idea to make message class for communication between two objects?为两个对象之间的通信创建消息类是一个坏主意吗?
【发布时间】:2020-03-18 16:21:56
【问题描述】:

在现有的源代码框架上,我试图让源代码在两个对象(例如 A 和 B)之间进行通信。

AFAIK,由于类型推断不完整,无法通过在每个对象中使用队列来传递消息。

例如(假设每个类定义在不同的头文件,A.h B.h),

A类:

B* b; // assume we have this declaration in class A
b->receiveMessageFromA(data); // object 'b' wants to receive a message from object 'a'

B 类:

A* a; // assume we have this declaration in class B
a->receiveMessageFromB(data); // object 'a' wants to receive a message from object 'b'

由于发生不完整的类型编译错误,即使我使用前向类声明也无法完成上述实现。

为了弥补这一点,我认为定义名为 MessageQueue 的类可以对此有所帮助。

现在,我想举一个简单的例子来定义类 A、B 和消息队列。

class Message { // Assume Request is defined somewhere
public: 
  std::vector<Request> messageFromA; // message q
  std::vector<Request> messageFromB; // message q
}

class A {
public:
  Message* msg;

  void sendMsgToB(Request req) {
    msg->messageFromA.push_back(req); // send message to B
  }
  void tick() {
    if (msg->messageFromB().size() != 0) {
      // if 'messageFromB' queue has elements, A can receive message from B
    }
  }
}
class B {
public:
  Message* msg;
  void sendMsgToA(Request req) {
    msg->messageFromB.push_back(req);
  }
  void tick() {
    if (msg->messageFromA.size() != 0) {
      // if 'messageFromA' queue has elements, B can receive message from A
    }
  }
}

设计class Message 是不是在两个类之间进行通信的错误选择?

听说有监听器/观察者模式,但是可能需要在现有框架中修改大量源代码,污染原有的设计模式。

【问题讨论】:

  • 我看到的消息的一般结构是一个数据字段的结构,称之为Message.. 每个类在构造时都可以采用std::queue&lt;Message&gt;&amp;。在创建A 和B 之前创建std::queue&lt;Message&gt;,然后将queue 传递给每个类构造函数。如果这是单线程的,你就完成了。如果它是多线程的,请确保包含mutex。如果类需要跨机器或跨时间或两者进行通信,请在发送数据之前对其进行序列化。

标签: c++ design-patterns


【解决方案1】:

由于发生不完整的类型编译错误,即使我使用前向类声明也无法完成上述实现。

当然可以。您可以使用以下顺序:

  1. 声明 A 和 B(按任意顺序)
  2. 定义 A 和 B(以任何顺序) - 它们应该只依赖于彼此的声明,例如 A* 或 B* 成员。确保不定义任何依赖于其他类定义的成员函数。
  3. 现在两个类都已定义,定义依赖于 A 和/或 B 定义的(成员)函数(以任何顺序) - 这可能涉及诸如 a-&gt;receiveMessageFromB(data); 和 b-&gt;receiveMessageFromA(data); 之类的东西

一个最小的例子:

// 1. declare the classes
struct A;
struct B;

// 2. define the classes
struct A {
    B* b;
    void receiveMessageFromB(int);
};
struct B {
    A* a;
    void receiveMessageFromA(int);
};

// 3. define the functions that rely on the class definitions
void A::receiveMessageFromB(int data) {
    if (data % 2)
        b->receiveMessageFromA(data - 1);
}
void B::receiveMessageFromA(int data) {
    if (data % 2)
        a->receiveMessageFromB(data + 1);
}

【讨论】:

  • 在class B 内调用a-&gt;receiveMessageFromB(data) 显示不完整的类型错误
  • @sungjuncho a-&gt;receiveMessageFromB(data) 语句是一个表达式。这是您必须在函数定义中编写的内容。在定义A之后再定义那个函数,就不会出现类型不完整的错误了。
  • 在我的框架中,A类和B类被定义为模板类,所有函数定义都在头文件中定义。为此,我认为我需要将定义和声明分开。这是你的意思吗?
  • @sungjuncho 是的,您必须将成员函数的定义和声明分开。我给你写了一个例子。
  • 感谢您的具体示例。顺便说一句,这样设计课程是个坏主意吗?或者像我提到的那样定义class Message怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 2012-10-15
相关资源
最近更新 更多