【问题标题】:c++ const member function returning reference to class memberc++ const成员函数返回对类成员的引用
【发布时间】:2014-05-06 15:39:13
【问题描述】:

如果我有类成员函数:

bar* foo::get_value() const
{
  return &_value;
}

编译器会抱怨

无法用 const bar * 类型的右值初始化 bar * 类型的变量

_value 不是类中的const

如果我有这个功能:

bar* foo::get_value() const
{
  return const_cast<bar *>(&_value);
}

效果很好。

我以为声明成员函数常量意味着你承诺不修改类的内部内容,但操作&amp; 似乎在const 成员函数中返回了一个常量指针。这是为什么呢?

【问题讨论】:

  • 你不能修改类的内部内容,因为它在 const 方法中是常量

标签: c++ reference


【解决方案1】:

当你声明一个函数const 时,你是说这是一个在对象的非常量和常量实例上都允许的函数。因为它可以在const 实例上调用,所以该函数不应改变对象。当您返回对内部对象的非常量引用时,您正在为调用者提供一种间接改变对象内部状态的方法。要解决此问题,请改为返回一个常量对象。

换句话说,而不是:

Bar* Foo::GetBar() const

做:

const Bar* Foo::GetBar() const

或者,更好的是:

const Bar& Foo::GetBar() const

正如您所观察到的,const_cast 允许您破坏对象的 const-ness。一般来说,你应该避免使用const_cast;使用它是一种代码味道,它破坏了预期的const 保证。

【讨论】:

    【解决方案2】:

    当一个对象实例声明为const时,它的所有成员变量都被视为const——也就是说,除了使用关键字mutable声明的成员之外。

    因此,理论上,您可以将_value 声明为mutable,这至少比const_cast&lt;&gt; 更可取-您可以绕过它。但它仍然不理想。正确的做法是提供两个重载:

    const bar* foo::get_value() const
    {
        return _value;
    }
    
    bar* foo::get_value()
    {
        return _value;
    }
    

    (更好的是使用引用或智能指针而不是原始指针)。

    【讨论】:

      【解决方案3】:

      问题是getter函数的返回类型。您将返回 bar* 而不是 const bar*。前者将允许get_value 函数的调用者修改对象。但是,您将 _value 声明为 const 是明确禁止的。

      您可以使用const_cast 绕过它,但这是不正确的。这就像告诉编译器“相信我,我知道我在做什么”,但在这种情况下,你不知道。您无法控制调用代码将对对象执行的操作。如果他们试图修改它——bam,未定义的行为。

      让自己的生活变得简单,只要让getter返回const bar*

      const bar* foo::get_value() const
      {
        return &_value;
      }
      

      请注意,编译器错误消息实际上告诉您需要对代码进行的更改。

      【讨论】:

        【解决方案4】:

        const 成员函数仅适用于 const 对象。使用 const 对象,您无法更改其成员变量。这就是为什么编译器不允许你创建一个指向 const 对象的成员变量的非 const 指针。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-01-08
          • 2021-08-10
          • 2015-06-10
          • 1970-01-01
          相关资源
          最近更新 更多