zoukankan      html  css  js  c++  java
  • C++ 之 常量成员函数

      常量成员函数 (const member function), 可读取类中的数据成员,但不能修改

    1  声明

    1.1  const 关键字  

      参数列表后,加 const 关键字,声明为常量成员函数,表明其不被允许修改类的数据成员

      下面的类,以年、月、日的形式来表示日期 (注意:年月日的声明顺序)

    class Date {
    public:
        int GetYear() const { return y_; }int GetMonth() const { return m_; }
        int GetDay() const { return d_; }
        void AddYear(int n); // add n years
    private:
        int y_, m_, d_;  
    };

      1) 如果常量成员函数,企图修改类的数据成员,则编译器会报错

    // error : attempt to change member value in const function
    int Date::GetYear() const
    {
        return ++y_; 
    }

      2) 如果在类外面,“定义” 常量成员函数 ( “定义” = 实现,即 implementation),则 const 关键字不可省略

    // error : const missing in member function type
    int Date::GetYear() 
    {
        return y_;
    }

    1.2  C++ 陷阱

      类中成员变量的声明顺序,决定了成员变量的初始化顺序。假设 Date 类中的构造函数为:

    public:
        Date() : y_(2016), m_(9), d_(22) {}

      此时,类中的成员函数,在类中的声明顺序 = 构造函数初始化列表顺序,故 y_, m_, d_ 都能被顺利的初始化为对应的值。

      而当成员变量,在类中的声明顺序 ≠ 构造函数初始化列表顺序 时,

    public:
        Date() : y_(2016), d_(22), m_(d_-13) {}

      根据成员变量的声明顺序,y_ 首先被初始化为 2016,然后再初始化 m_,但由于 d_ 并未被初始化,所以 m_ 的值是随机的,最后初始化 d_ 为 22

      这是因为,类的成员变量在初始化时,其初始化的顺序只与声明顺序有关,而与在初始化列表中的顺序无关。

    2  调用

      一个常量成员函数,可以被 const 和 non-const 类对象调用; 而非常量成员函数,例如 AddYear(),则只能被 non-const 型类对象调用。

    void  Date::AddYear(int n)
    {
        y_ += n;  
    }

      调用函数如下:

    void f(Date& d, const Date& cd)
    {
        int i = d.GetYear();    // OK
        d.AddYear(1);        // OK
    int j = cd.GetYear(); // OK cd.AddYear(1); // error }

      此时,const 修饰函数形参,是 “接口” 的常用指定形式, 这样 数据 可以传递给 函数 而 本身不被修改

      C++ 中的类型转换 const_cast,可以移除对象的 const 属性,具体使用为: const_cast<T>(expression)

      则上例中,要使 const 型类对象,调用类的 non-const 成员函数,可修改代码如下:

    void f(Date& d, const Date& cd)
    {
        int j = cd.GetYear();    // OK
        const_cast<Date&>(cd).AddYear(1); 
    }

      这种做法虽然是可以的,但它破坏了使用 const 来指定 “接口“ 的本意,并不推荐。


    3  解释

      this 指针 默认是指向 non-const 型类对象的 const 型,因此,不能将 this 指针和 const 型类对象绑定,即 const 类对象无法调用类的成员函数

    // 默认的 this 指针,指向 non-const 类对象
    Date * const this;

       在成员函数声明的参数列表后加 const 后缀,表明其 this 指针指向 const 型类对象,如此, const 型类对象便可以调用常量成员函数了

    // 常量成员函数中的 this 指针,指向 const 类对象
    const Date * const this;

      

    小结:

    1) 类成员函数声明中的 const 后缀,表明其 this 指针指向 const 型类对象,因此该 const 类对象,可以调用常量成员函数 (const member function)

    2) 一个成员函数,如果对数据成员只涉及读操作,而不进行修改操作,则尽可能声明为常量成员函数

    参考资料:

     <C++ Programming Language_4th> ch 16.2.9.1

     <C++ Primer_5th> ch 7.1.2

     <Effective C++_3rd> Item 3, item 27

     <More Effective C++> Item 2

     <剑指 offer> 第 7 章

  • 相关阅读:
    OpenCV --- 2.4.8组件结构全解析
    综合博客
    设计模式之适配器模式
    android 面试题
    ANDROID 中设计模式的采用--结构型模式
    技术前线
    八大排序算法
    android 面试题
    Android控件——ViewPager
    Bugly
  • 原文地址:https://www.cnblogs.com/xinxue/p/5405362.html
Copyright © 2011-2022 走看看