【问题标题】:What's the difference between a const member function and a non-const member function?const 成员函数和非常量成员函数有什么区别?
【发布时间】:2010-06-18 02:22:30
【问题描述】:

我对 const 版本和非常量版本的成员函数很困惑,如下所示:

value_type& top() { return this.item }
const value_type& top() const { return this.item }

这两个函数有什么区别?会在什么情况下使用?

【问题讨论】:

  • 您应该考虑购买一本在The Definitive C++ Book Guide and List 中列出的优秀入门书籍。
  • Nitpick:mutable 是一个有其自身含义的 C++ 关键字,而不仅仅是 const 的反义词。您的问题会更清楚地表述为“const 成员函数和非 const 成员函数有什么区别?”
  • @Josh - 关于明确消歧的好点,但我认为“可变”在编程语言中是“可以修改的东西”的常见描述。
  • @Josh:我同意并相应地更新了问题。如果有人对此感到冒犯,请随时回滚:)
  • @Josh:你是对的。 mutable 不如 non-const 精确

标签: c++


【解决方案1】:

简而言之,它们用于为您的程序添加“常量正确性”。

value_type& top() { return this.item }

这用于提供对item 的可变访问。它用于修改容器中的元素。

例如:

c.top().set_property(5);  // OK - sets a property of 'item'
cout << c.top().get_property();  // OK - gets a property of 'item'

此模式的一个常见示例是返回对具有vector::operator[int index] 的元素的可变访问。

std::vector<int> v(5);
v[0] = 1;  // Returns operator[] returns int&.

另一方面:

const value_type& top() const { return this.item }

这用于为const 提供对item 的访问权限。它比以前的版本限制更多 - 但它有一个优点 - 你可以在 const 对象上调用它。

void Foo(const Container &c) {
   c.top();  // Since 'c' is const, you cannot modify it... so the const top is called.
   c.top().set_property(5);  // compile error can't modify const 'item'.
   c.top().get_property();   // OK, const access on 'item'. 
}

以向量为例:

const std::vector<int> v(5, 2);
v[0] = 5;  // compile error, can't mutate a const vector.
std::cout << v[1];  // OK, const access to the vector.

【讨论】:

    【解决方案2】:

    如果成员函数在具有 const 限定的对象上调用,则将调用 const 限定的成员函数。

    如果在非 const 限定的对象上调用成员函数,则将调用非 const 限定的成员函数。

    例如:

    MyStack s;
    s.top(); // calls non-const member function
    
    const MyStack t;
    t.top(); // calls const member function
    

    请注意,在对对象的引用或通过指向对象的指针调用成员函数时适用相同的规则:如果指针或引用指向 const 对象,则将调用 const 成员函数;否则将调用非常量成员函数。

    【讨论】:

    • 如果有像value_type& top() const { return this.item }这样的memeber函数,非const对象可以调用吗?如果添加const like function foo() const,就意味着它会改变当前对象,对吗?如果是这样,它应该由非常量或常量对象调用。对吗?
    • 如果一个对象不是 const 并且成员函数同时存在 const 和非常量重载(并且这些重载是相同的),则将调用非常量成员函数。您可以通过将对象强制转换为 const 引用然后在其上调用成员函数来“强制”调用 c​​onst 成员函数。 const 成员函数不能修改对象的任何非可变成员,也不能调用任何非 const 成员函数。
    • @Yongwei Xing,补充詹姆斯的回应,如果你只给出一个“const”重载,它将被 const 和非 const 对象使用。仅当您同时具有 const 和非常量重载时,它们才会使用不同的版本。一般来说,如果某个东西可以声明为“const”,那么它应该是……非const对象可以调用const和非const函数,而const对象只能调用const限定的成员函数。
    【解决方案3】:

    如果你有

    class Foo
    {
        value_type& top() { return this.item }
        const value_type& top() const { return this.item }
    }
    

    如果你有

    Foo foo;
    const Foo cfoo;
    

    调用top()时的返回类型如下:

    value_type& bar = foo.top();
    const value_type& cbar = cfoo.top();
    

    换句话说 - 如果你的类有一个常量实例,函数的 const 版本将被选为要调用的重载。

    这样做的原因(在这种特殊情况下)是为了让您可以从类的 const 实例中给出对成员的引用(如 item 在这种情况下),并确保它们也是 const - 因此不可修改因此保留了它们来自的实例的常量性。

    【讨论】:

      【解决方案4】:

      当成员函数声明为const 时,传递给函数的隐式this 指针参数被键入为指向常量对象的指针。这允许使用 const 对象实例调用函数。

      value_type& top();    // this function cannot be called using a `const` object
      const value_type& top() const; // this function can be called on a `const` object
      

      【讨论】:

        【解决方案5】:

        value_type&amp; top() { return this.item; } 确保调用对象的数据成员可以修改或返回值可以修改。

        value_type&amp; top() const { return this.item; } 确保调用对象的数据成员不能被修改,但返回值可以。因此,例如,如果我执行value_type item_of_x = x.top();,则可以修改item_of_x,但不能修改x。否则,会出现编译器错误(例如在函数体中包含代码this.item = someValue;)。

        const value_type&amp; top() { return this.item; } 保证调用对象的数据成员可以修改,但返回值不能。这与上面讨论的相反:如果我执行const value_type item_of_x = x.top();item_of_x 不能修改,但x 可以。 注意 value_type item_of_x = x.top(); 仍然允许修改 item_of_x,因为 item_of_x 现在是非常量的。

        const value_type&amp; top() const { return this.item; } 确保调用对象的数据成员和返回值都不能被修改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-04
          • 2021-11-03
          • 2016-08-17
          • 2016-05-01
          • 2019-07-09
          相关资源
          最近更新 更多