【问题标题】:Unique Identifier for sent messages in good programming practice良好编程习惯中已发送消息的唯一标识符
【发布时间】:2015-02-26 15:56:50
【问题描述】:

系统发送 xml 警告消息。为了将 xml 文件放在一起,创建了一个类,以便可以在将其转换为 xml 之前生成警告。每条消息都必须有一个唯一的 ID。 有多独特? ID 从 3400 到 3500。如果达到最大值,则重置 ID。

#ifndef WARNINGMESSAGE_H
#define WARNINGMESSAGE_H
#include <ctime>

static unsigned int control_ID = 3399;
//Effect Codes:
const unsigned int TRAFFIC_FREE = 2;
//(...)
class WarningMessage{
 public:
  //setters
  void setActionID();

  //getters
  //(...)
 private:
  unsigned int actionID;    //to be controlled by control_ID
 };
#endif // WARNINGPARAMVEHICLE_H

而在cpp文件中,当需要设置消息的id时,执行如下:

#include "project/include/warningmessage.h"

//setters
void WarningParamVehicle::setActionID(){
 if(control_ID == 3500){
  control_ID = 3399;
 }
 control_ID++;
 actionID = control_ID;
}

另一个重要的细节是,该类消息的内存空间只给出一次。每次必须发送另一条消息时,实例都会被删除并重新创建:

void WarningDetector::createWarning(){
 delete currentWarningMessage;  // delete previous warning instance
 currentWarningMessage = new WarningMessage();
 (...)
}

最后,currentWarningMessage 在警告检测器中被声明为一个指针:

WarningMessage* currentWarningMessage;

我可以注意到在头文件中和类范围之外声明变量 control_ID 的不良编程习惯,但是,给定这样的场景编码看起来已优化。有没有更好的方法来解决这里看到的这个唯一标识符问题?提前非常感谢

【问题讨论】:

  • “在头文件和类范围之外声明变量 control_ID 的不良编程习惯” --- 那么,将变量放在类范围内怎么样?
  • 如果您有一个WarningDetector 类来创建警告,为什么不将control_ID 放在该类中,而不是使用setActionID,只需在构造函数中传递id。新的警告消息(nextId)
  • 顺便说一句,目前,每个翻译单元都有一个control_ID,包括标题:/
  • @tenfour 如果我没记错的话,将变量放在类范围内会使我在创建新的 WarningMessage 实例时失去计数。
  • @JoãoAugusto 的确,到目前为止,您的回答似乎是我拥有的最佳选择。

标签: c++ uniqueidentifier


【解决方案1】:

良好的编程实践可以包括单一职责。例如,为当前消息设置动作 id 可以与决定下一条消息的动作 id 分离。这可以在构建 WarningMessage 期间发生异常时实现一致的行为(如果您有机会修复异常的原因,您可能希望再次尝试创建 WarningMessage 并期望相同的 actionId)。

要解决这个问题以及上面的其他 cmets,您可以:

  • 将 control_ID 设为 WarningMessage 的私有静态成员(setActionID 当前是 WarningMessage 的成员)
  • 移除 public setter setActionID 并在初始化列表中初始化 actionID
  • 管理control_ID,构造函数中的最后一件事(以防出现异常)

在标题中:

#ifndef WARNINGMESSAGE_H
#define WARNINGMESSAGE_H
#include <ctime>

//Effect Codes:
const unsigned int TRAFFIC_FREE = 2;
//(...)
class WarningMessage{
public:
  WarningMessage();
  //remove public setters if your use case doesn't require them
  //getters
  //(...)
private:
  // deconstructing control_ID
  static const unsigned ID_COUNT = 100;
  static const unsigned ID_START = 3400;
  static unsigned idOffset = 0;
  const unsigned int actionID;    //to be controlled by control_ID
};
#endif // WARNINGPARAMVEHICLE_H

在cpp文件中:

#include "project/include/warningmessage.h"

unsigned WarningMessage::idOffset = 0;

WarningMessage::WarningMessage()
: actionId(ID_START + idOffset) /* ... */
{
    // increment idOffset only when you are sure that it is safe
    ++idOffset;
    idOffset %= ID_COUNT;
}

请注意,这不适用于多线程环境,但这似乎不是您目前关心的问题

【讨论】:

  • 在创建一个新的WarningMessage 实例时,我不会丢失id 的计数(idOffset 将重新启动为0)吗?当前,每条新消息都带有一个新的WarningMessage 实例。你是对的,多线程现在不是我关心的问题。谢谢你的帮助。
  • @okaitt no idOffset 不会在您创建新实例时重新启动为 0。 Static members variables 被类中的所有对象共享。
【解决方案2】:

我将创建 2 个常量 IDMIN = 3499IDMAX = 3500 以避免在实现文件中出现幻数。这些常量应该是类WarningMessage 的静态常量成员。

我会在方法WarningParamVehicle::setActionID 中将control_ID 设置为静态变量(不是WarningMessage::setActionID 吗?)。然后它会给出:

class WarningMessage{
 public:
  static const int IDMIN = 3499;
  static const int IDMAX = 3500;
  //setters
  void setActionID();
  ...

及以后的实施:

void WarningParamVehicle::setActionID(){
 static int control_ID = WarningMessage::IDMIN;

 if(control_ID == IDMAX){
  control_ID = IDMIN;
 }
 control_ID++;
 actionID = control_ID;
}

【讨论】:

  • 在创建新的WarningMessage 实例时,我不会失去id 的计数吗?当前,每条新消息都带有一个新的WarningMessage 实例。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2013-09-11
  • 1970-01-01
  • 2013-11-29
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多