C++中的常对象与常成员

Posted by WSY on September 7, 2019

概述

  C/C++用关键字const来定义常量,常对象和常成员概念的建立,明确规定了程序中各种对象的变与不变的界线,从而进一步增强了C++程序的安全性和可控性。 本文总结一下常对象、常数据成员、常成员函数的概念和特性。

常对象

  在程序中,我们有时候不允许修改某些特定的对象。如果某个对象不允许被修改,则该对象称为常对象。C++编译器对常对象(const对象)的使用是极为苛刻的:

  • const 对象不能被赋值,所以必须在定义时由构造函数初始化。
  • const 对象不能访问非常成员函数,只能访问常成员函数。常成员函数是常对象唯一的对外接口方式 。

常对象定义格式如下: 类型 const 对象名; 或 const 类型 对象名;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;

class Clock
{
    private:
      int H,M,S;
    public:
      Clock(int H=0,int M=0,int S=0)
      {
         this->H=H, this->M=M, this->S=S;
      }
      void ShowTime()
      {
         cout<<H<<":"<<M<<":"<<S<<endl;
      }
      void SetTime(int H=0,int M=0,int S=0)
      {
          this->H=H, this->M=M, this->S=S;
      }
 };

int main( )
{
        const  Clock  C1(9,9,9);      //定义常对象C1
        Clock  const  C2(10,10,10);   //定义常对象C2
        Clock  C3(11,11,11);
        //  C1=C3;                    //错误!C1为常对象, 不能被赋值
        //  C1.ShowTime();            //错误!C1为常对象, 不能访问非常成员函数
        //  C1.SetTime(0,0,0);        //错误!C1为常对象,不能被更新!
        C3. ShowTime();
        return 0;
}

/****************运行结果****************/
11:11:11

常数据成员

  使用 const 说明的数据成员称为常数据成员。常数据成员的定义与一般常变量的定义方式相同,只是它的定义必须出现在类体中。常数据成员使用时应注意:

  • 常数据成员必须进行初始化,并且不能被修改。
  • 常数据成员的初始化只能通过构造函数的初始化列表进行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;
class A
{
    private:
        const int& r;          //常引用数据成员
        const int a;           //常数据成员
        static const int b;    //静态常数据成员
    public:
        A(int i):a(i),r(a)     //常数据成员只能通过初始化列表来获得初值
        {
            cout<<"constructor!"<<endl;
        }
        void display()
        {
            cout<<a<<","<<b<<","<<r<<endl;
        }
};
const int A::b=3;              //静态常数据成员在类外说明和初始化

int main()
{
    A a1(1);
    a1.display();
    A a2(2);
    a2.display();
    return 0;
}

/****************运行结果****************/
constructor!
1,3,1
constructor!
2,3,2  

常成员函数

  在定义时使用const关键字修饰的用于访问类的常对象的函数, 称为常成员函数。常成员函数的说明格式如下:返回类型  成员函数名 (参数表) const; 在定义与使用常成员函数时要注意:

  • 常成员函数不能修改对象的数据成员,也不能调用该类中没有用const修饰的成员函数。
  • const是函数类型的一个组成部分,因此在函数实现部分也要带有const关键字。
  • 常对象只能调用它的常成员函数,而不能调用其他成员函数。这是C++语法机制上对常对象的保护,也是常对象唯一的对外接口方式 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Date
{
    private:
        int  Y, M, D;
    public:
        int year() const;
        int month() const;
        int day() const  {return D;};
        int day()  {return D++;}
        int AddYear(int i)  {return Y+i;};
};

int Date::month()            //错误,常成员函数实现不能缺少const
{
    return M;
}

int Date::year()const
 {
      // return Y++;         //错误,常成员函数不能更新类的数据成员
      return Y;
 }

Date const d1;
// int j = d1.AddYear(10);   //错误,常对象不能调用非常成员函数
int j = d1.year();           //正确,常对象可以调用常成员函数

Date d2;
int i = d2.year();           //正确,非常对象可以调用常成员函数
d2.day();                    //正确,非常对象可以调用非常成员函数