【问题标题】:force preference of const-version?强制使用 const 版本?
【发布时间】:2013-05-30 17:00:45
【问题描述】:

假设我有

class A {
  double a;
  double Value() const {
    return a;
  }

  double& Value() {
    return a;
  }

}

//later:
A foo;
double b = foo.Value();

现在,将调用非常量版本。 有没有强制使用 const 版本的好方法?我认为有演员表是可能的,但我认为它不是很优雅。

【问题讨论】:

  • 允许只有const 不同的重载的全部意义在于区分const 对象与非const 对象的调用。如果您不想要这种行为,请不要定义两个重载! (见parashift.com/c++-faq/const-overloading.html
  • @OliCharlesworth 不幸的是,我定义了 A 类,但我无法更改它
  • 为什么不删除非常量版本?
  • 您为什么要这样做?如果两个重载的语义差异足以满足这一要求,那么它们应该是彼此的重载。

标签: c++


【解决方案1】:

你可以把它投给const

double b = static_cast<const A&>(foo).Value();

(我认为我从来没有明确地将const 添加到变量中。我不确定static_cast 是否比const_cast 更合适。)

【讨论】:

  • 顺便说一句,你是对的。 static_cast 是正确的演员阵容。
  • 感谢@GManNickG 的验证。
  • @GManNickG:你能解释一下为什么 const_cast 不是正确的演员阵容,而你只想添加 constness 吗?
  • @LightnessRacesinOrbit:这是关于使用较弱的演员阵容。 const_cast 可以删除 const,因此使用它会打开错误之门。也就是说,使用它不是不正确,但也不是必须的。由于您可以随时添加 const,static_cast 是最弱的演员,可以让您表达这种愿望。你可以想象一个 const volatile 变量被传递给一个想要添加 const 的模板函数 - const_cast&lt;const T&amp;&gt; 实际上会剥离 volatile 。我认识到这本质上与纯粹的理论相去甚远。 :)
  • @GManNickG:我不同意static_cast 是较弱的演员。通过使用它,您可以通过更多方式更改类型,而不是更改其constness。相反,const_cast 在您使用 const 时无法删除它,因为那里没有 const。虽然 blergh 关于volatile 很好但是来吧^_^
【解决方案2】:

比强制转换更漂亮——分配给 const 引用不需要显式强制转换:

A foo;
const auto& cfoo = foo;
double b = cfoo.Value(); // will use Value()const

在实践中,如果您尽可能在所有函数参数中虔诚地使用const,那么您很可能会在某个时候将foo 传递给bar(const A&amp; x)

【讨论】:

  • 老实说,现在我们有了auto,这可能就是我要做的。
【解决方案3】:

您可以使用代理完成您似乎想要的事情:

class A {
  double a;

  class proxy { 
      A &a;
  public:
      proxy(A &a) : a(a) {}

      operator double() const { return a; }

      proxy operator=(double d) { a.a = d; return *this; }
  };

public:

  proxy Value() {
    return proxy(*this);
  }
}

// ...

double d = foo.Value();   // will use proxy::operator double.
foo.Value() = 1.0;        // will use proxy::operator=

这确实需要对您的class A 进行(内部)修改,但不需要对使用它的代码进行修改。但是,它会将读取和写入成员数据的代码分开,因此您可以分别在每个代码上设置断点。

【讨论】:

    【解决方案4】:

    你不能做得那么优雅,但最不冗长的应该是定义

    class A {
    ...
    
    const A * operator->() const
    {
       return this;
    }
    
    }
    

    并使用它

    foo->Value();
    

    而不是

    foo.Value();
    

    仅适用于 const 版本

    【讨论】:

    • 朋友不要让朋友超载他们的运营商
    • 各位,你们太认真了=)
    【解决方案5】:

    从 C++17 开始,我们有 std::as_const(),它为您转换了对 const 引用的引用。例如:

    #include <utility>
    ...
    A foo;
    double b = std::as_const(foo).value();
    

    【讨论】:

      猜你喜欢
      • 2018-10-12
      • 2017-02-01
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 2019-08-22
      • 2012-04-23
      相关资源
      最近更新 更多