好的做法:常量到非常量的转换

Good practice: Constant to non-constant cast

本文关键字:常量 转换 非常      更新时间:2023-10-16

当函数不修改对象参数时,我总是让它请求常量引用,即使引用的对象不是真正的常量。这有错吗?

对于包装器类,我想这样写:

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

构造函数不修改基类,所以要求常量引用。

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

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

有更好的方法吗?

有什么公认的惯例吗?

当你选择你的参数作为一个const引用,你告诉用户"你可以相信,如果你传递给我一个对象,它不会被修改[通过这个引用]†。"您应该尽可能多地这样做,因为用户可以通过查看类型来更多地了解函数将做什么和不做什么。此外,传递可变引用可能导致难以推理的代码。

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

不仅如此,您当前的实现还允许未定义行为。即使最初声明为const的对象被赋予Wrapper,它也不会在意。它抛弃了它的const属性,并允许其他成员函数修改它。修改一个原来是const的对象是未定义的行为。

†参见6502的注释

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