可以用C++制作"未来安全"比较运算符吗?

Joh*_*cha 10 c++ class operator-overloading

问候所有,

是否有可能在C++中创建一个未来安全的比较运算符(==)?

我遇到的问题是我们有一个有多个成员的班级.我们有一个比较运算符来验证对象的instance-1是否与instance-2具有相同的值.

即我们可以做到

class blarg {
    .....
};

.....

blarg   b1(..initializers...);
blarg   b2 = b1;

if (b1 == b2) {
    ... then do something ....
}
Run Code Online (Sandbox Code Playgroud)

但是,我有一个同事在该类中添加了一个新成员,但未能更新比较运算符.这导致我们需要一段时间才能弄明白的问题.

有没有一种编码习惯,我的意思是其他比代码审查(失败对我们来说),或编码方法,设计,模板,魔豆,不管这可能有助于避免这样的情况?

我的第一反应是使用memcmp命令.但是,在阅读" 比较C与C++中的结构 "的堆栈溢出条目后,我发现这可能会有问题,因为C++类不仅仅包含内部的成员数据.

别人怎么处理这个?

预先感谢您的帮助.

Joh*_*ing 8

嗯,显而易见的解决方案是在扩展原始类时要更加小心.:)"更加小心"包括代码评论,类似的东西,但显然这不是万无一失的.

因此,从哲学的角度来解决这个问题,而不是技术问题,通常可以提供洞察力.在这种情况下的哲学是成为一个偏执的程序员.假设您今天编写的代码将在几个月或几年后被打破.(每个编辑@下面诺亚的评论:通常情况下,这傻子就是我自己作为一个偏执的程序员保护我从我自己可能比任何人都多.)如果你可以做一些事情,以确保当笨蛋不会破坏你的代码的东西失败在产品发货之前,这会有所帮助.

我喜欢使用的两件事是静态断言和单元测试.可以在operator==代码中使用静态断言来验证sizeof您的类是否符合预期.例如:

bool MyClass::operator==(const MyClass& rhs) const
{
  static_assert(sizeof(MyClass) == sizeof(foo_) + sizeof(bar_))
  ...
}
Run Code Online (Sandbox Code Playgroud)

...其中foo_bar_是成员变量.当类的大小发生变化时,这将破坏编译.

由于静态断言通常采用模板类的形式,当表达式为false时将无法编译.这可能有点难以写(但这是一个有趣的练习 - 考虑如果你试图将一个char test_[0]成员添加到一个类会发生什么).幸运的是,这个轮子已经被发明了.有关示例,请参阅Boost,我认为新的MSVC编译器也附带一个.

  • 我认为硬编码已知的大小将起作用而不是使用`sizeof(MyClass)`.至少在你尝试另一个编译器或不同的编译器开关之前...... (3认同)
  • 这种方法背后的想法很好,但我认为由于成员对齐的原因,它经常会失败. (2认同)
  • @wilhelmtell:max_align技巧如何帮助补偿类的*成员*的对齐? (2认同)

Edw*_*nge 7

好的,现在回答.

对你的对象进行适当的单元测试应该完全改变了这种错误.这正是他们擅长指出的那种东西.

  • 只要将成员变量添加到类中的程序员也在单元测试中添加适当的检查以进行相同的更改.他未能更新`operator ==`,那么他记得更新单元测试的可能性是多少? (4认同)
  • 两个回应.首先,正确使用单元测试要求您首先编写测试.开发人员不应该忘记他们是否遵循这种方法.其次,如果有问题的测试是对==的测试,那么如果它有这样的操作符就应该如此,那么更新它的失败仍然会导致编译失败并提醒开发者他的错误.但不,尽管它大大降低了螺丝拧紧的可能性,但仍然不完美. (2认同)
  • @Daniel - 我在C++中遇到的TDD唯一的问题就是糟糕的设计选择......这些问题几乎都是由于没有开始使用TDD而创建的. (2认同)