良好做法:不变为非恒定演员

时间:2014-06-23 16:56:15

标签: c++ casting const conventions

当一个函数没有修改一个对象参数时,即使被引用的对象不是真的不变,我总是让它要求一个常量引用。这是错的吗?

对于包装类,我想写一下:

template<class B>
class Wrapper{
private:
  B* base_;
public:
  Wrapper(const B& b) { base_ = const_cast<B*>(&b); }
  void ModifyBase();
};

构造函数不修改基数,因此它要求持续引用。

包装器有一些方法需要修改基类,因此它需要存储一个非常量指针(因此转换)。

我觉得我的解决方案不是最好的。

有更好的方法吗?

是否有任何公认的惯例?

2 个答案:

答案 0 :(得分:9)

当您选择参数作为const参考时,您会告诉用户&#34;您可以相信,如果您传递给我一个对象,它将不会被修改[通过此参考]†&#34;你应该尽可能经常这样做,因为用户可以更多地了解你的功能,并且只是通过查看类型才能做到。此外,传递可变引用可能会导致代码难以推理。

但是,在你的问题中,你的const并没有说实话。它抛弃了const并存储了一个非const指针 - 这意味着该对象很可能会被修改。你欺骗了用户!构造函数本身对该对象没有任何作用并不重要。它允许其他成员函数修改它。这是不好的行为。您的构造函数不应该使用const引用。

不仅如此,您当前的实现还允许未定义的行为。即使最初声明为const的对象被提供给您的Wrapper,它也不会关心。它抛弃了它的const并允许其他成员函数修改它。修改最初为const的对象是未定义的行为。

†见6502的评论

答案 1 :(得分:1)

ctor不会改变ctor中的对象并不重要,ctor完成后会发生什么,这就是为什么你需要非const 1}}指向B的对象指针。所以它与传入的B对象的所有权和生命周期有关:如果你想获得所有权(通过&引用,那么该对象必须是非const,因为它如果你想简单地复制传入的B对象,那么就不要使用引用,按值传递并存储指向副本的指针。