从std:string派生以添加typedef和enums

时间:2015-04-27 08:17:17

标签: c++ c++11 inheritance stdstring

对于客户端和服务器之间交换的UDP包,我想支持两种字符串字段:

  • 以null结尾的名为cstring
  • 的c-string
  • 前面有uint8_t大小字段vstring
  • 的字符串

要自我记录我们的包的布局,我想使用简单的结构声明:

struct ABC {
  vstring a;
  cstring b;
}

并在de / serialization函数中调用重载函数get(char*, vstring& v)get(char*, cstring&),如下所示:

void deserialize(const char* bytes, ABC& msg) {
  get(msg.a);
  get(msg.b);
}

void serialize(char* bytes, const ABC& msg) {
  put(msg.a);
  put(msg.b);
}

但是,对于用户vstringcstring,理想情况下应该像普通std::string一样。

我的第一个想法是简单地使std::string成为vstringcstring的公共基础,以便在过载解析期间可以区分这两个类,但对用户来说行为相同。但由于不鼓励从std::string派生,我不确定该怎么做。

3 个答案:

答案 0 :(得分:4)

std::string派生的危险是析构函数不是虚拟的,所以有人可能会这样做:

std::string* p = new vstring;
delete p;

你有未定义的行为。如果您认为像这样的代码没有机会在您的环境/系统中编写,请将自己敲出来并从std::string派生。

准则:

  • 如果vstringcstring类仅在非常有限的受控环境中使用 - 最好是由一个或少数开发人员与您进行预期沟通 - 并且监控实际使用情况,或者很明显动态分配和多态性不会被滥用来处理它们,一切都很好。

  • 在另一个极端 - 如果他们在你的接口中有未指定数量的不受控制的代码,那么通知所有未来的客户开发人员这个问题是不切实际的 - 这不是好事,而且是一个场景你不应该从没有虚拟析构函数的类型派生出来。

那就是说,你真的需要对类型中的序列化样式进行编码吗?他们必须编写序列化和反序列化例程,列出要序列化的字段,并且它们可以指定格式(NUL终止与长度前缀或其他任何其他)。

答案 1 :(得分:2)

在意识形态上,序列化的方式不应该影响数据的类型,所以我最好做这样的事情:

void serializeNullTerminated(char* bytes, const std::string& msg);
void deserializeNullTerminated(const char* bytes, std::string& msg);

void serializeWithSize(char* bytes, const std::string& msg);
void deserializeWithSize(const char* bytes, std::string& msg);

或者将附加参数传递给函数:

void serialize(SerializationType st, char* bytes, const std::string& msg);
void deserialize(SerializationType st, const char* bytes, std::string& msg);

或者你可以制作模板:

template<SerializationType st>
void serialize(char* bytes, const std::string& msg);
template<SerializationType st>
void deserialize(const char* bytes, std::string& msg);

关键是,用户不必处理不同类型的字符串,在他们的代码中,他们只需要选择序列化/反序列化的方式。

答案 2 :(得分:1)

您必须将计算与消息分离。因此,在您的程序中,您使用std::string,当您需要发送/接收字符串时,您传递的消息符合您的协议。

因此,您的库/应用程序/唯一的公共接口应该是这样的:

int send_message(std::string const &s, int mode, ... destination ... etc);
int receive_message(std::string &s, int mode, ... source ... etc);

(可能char *c的{​​{1}}(以null结尾)重载。

模式为标记sMODE_CSTRING

内部发送/接收:

  • 以空字符结尾的字符或
  • 的向量
  • 大小,然后是人物的矢量。

您甚至不需要为MODE_VSTRINGcstring创建课程。