C++ const的使用

const 对象的一般形式

       ● 类型名 const 对象名[(构造实参表列)];
       ● const 类型名 对象名[(构造实参表列)];
       注意:常对象必须要有初值(因为以后不能改值了)。

限定作用

       定义为const的对象的所有数据成员的值都不能被修改。
       凡出现调用非const的成员函数,将出现编译错误。但构造函数除外。

1
2
3
Time const t1(12,34,46); // t1是常对象
t1.set_Time(); // 编译错误PE, 非const成员函数
t2.show_Time(); // 错误,非const成员函数

mutable

       对数据成员声明为mutable(易变的)时,即使是const对象,仍然可以修改该数据成员值。

常对象成员

常数据成员

       使用const说明的数据成员称为常数据成员,其值是不能改变的。
       如果在一个类中说明了常数据成员,那么构造函数就只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Time
{
const int hour; // 声明hour为常数据成员
Time(int h):hour(h){} // 通过参数初始化表对常数据成员hour初始化
};
class Time
{
const int hour; // 声明hour为常数据成员
Time(int h)
{
hour = h; // 错误
}
};

       常数据成员举例

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
#include <iostream.h>
class Date
{
public:
Date(int y,int m,int d);
void showDate();
const int &r;
private:
const int year;
const int month;
const int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d),r(year){ }
inline void Date::showDate()
{
cout<<"r="<<r<<endl;
cout<<year<<"."<<month<<"."<<day<<endl;
}
int main()
{
Date date1(1998,4,28);
date1.showDate();
return 0;
}

常成员函数

       在类中使用关键字const说明的函数为常成员函数。
       常成员函数的说明格式如下:
       类型说明符 函数名(参数表)const;

1
2
3
4
5
void show_Time() const; // 注意const的位置在函数名和括号之后
void Time::show_Time const
{
cout << hour << minute << sec << endl;
}

       注意:const是函数类型的一个组成部分,在声明函数和定义函数时都要有const关键字,在调用时不必加const。
       常引用作函数形参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream.h>
int add(const int& i,const int& j);
int main()
{
int a=20;
int b=30;
cout<<a<<"+"<<b<<"="<<add(a,b)<<endl;
return 0;
}
int add(const int& i,const& j)
{
return i+j;
}

       如果将一个对象说明常对象,则通过该对象只能调用它的常成员函数,而不能调用普通成员函数。而且常成员函数也不能更新对象的数据成员。
       常成员函数的使用

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
#include <iostream.h>
class Date
{
public:
Date(int y,int m,int d);
void showDate();
void showDate() const;
private:
int year;
int month;
int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d){ }
void Date::showDate()
{
cout<<"ShowDate1:"<<endl;
cout<<year<<"."<<month<<"."<<day<<endl;
}
void Date::showDate() const
{
cout<<"ShowDate2:"<<endl;
cout<<year<<"."<<month<<"."<<day<<endl;
}
int main()
{
Date date1(1998,4,28);
date1.showDate();
const Date date2(2002,11,14);
date2.showDate();
return 0;
}

       常成员函数只能引用本类中的数据成员,而不能修改它们,即成员数据不能作为语句的左值。(注意:可以改mutable成员)
       const对象及mutable成员

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 Time
{
public:
Time()
{
hour = 0;
minute = 0;
}
void set_Hour(int h) const { hour = h;}
void set_Minute(int m) { minute = m; }
void show_Time() const
{ cout<<hour <<":"<<minute << endl; }
private:
mutable int hour;
int minute;
};
int main()
{
Time t1;
t1.set_Hour(8);
t1.set_Minute(8);
t1.show_Time();
Time const t2;
t2.set_Hour(8);
t2.set_Minute(8);
t2.show_Time();
return 0;
}

常成员的使用

       ● 如果在一个类中,有些数据成员的值允许改变,另一些数据成员的值不允许改变,则可以将一部分数据成员声明为const,以保证其值不被改变,可以用非const的成员函数引用这些数据成员的值,并修改非const数据成员的值。
       ● 如果要求所有的数据成员的值都不允许改变,则可以将所有的数据成员声明为const,或将对象声明为const(常对象),然后用const成员函数引用数据成员,这样起到“双保险”的作用,切实保证了数据成员不被修改。
       ● 如果已定义了一个常对象,则只能调用其中的const成员函数,而不能调用非const成员函数(不论这些函数是否会修改对象中的数据)。如果需要访问对象中的数据成员,可将常对象中所有成员函数都声明为const成员函数,但应确保在函数中不修改对象中的数据成员。

指向常对象的指针变量

指向常对象的指针变量的一般形式

       const 类型 ✱指针变量名

1
2
3
const char *pc; // pc 指向的 char 是const型的
*pa = 'a'; // 错误:pa 指向的目标不能改变
pa++; // 正确, pa 本身的值可以改变

1
2
3
Time t1;
const Time *pt;
*pt = t1; // 错误:pt指向的目标不能改变

关于指向常对象的指针变量的说明

       ● 指向常对象(变量)的指针变量,不能通过它来改变所指向目标对象的值,但指针变量的值是可以改变的。
       ● 如果被声明为常对象(变量),只能用指向常对象(变量)的指针变量指向它,而不能非const型指针变量去指向它。

1
2
3
const int a = 10, b = 20;
const int *pa = &a; // 正确
int *pb = &a; // 错误:非 const 型指针

       ● 指向常对象(变量)的指针变量除了可以指向常对象(变量)外,还可以指向未被声明为const的对象(变量)。此时不能通过此指针变量改变该变量的值。

1
2
pa = &b; // 正确:也可指向非 const 型的变量
*pa = 30; // 错误:指向 const 型的指针不能改目标值

       ● 指向常对象(变量)的指针变量可以指向const和非const型的对象(变量),而指向非const型变量的指针变量只能指向非const的对象(变量)。

1
2
const int *pa = &b; // 正确
int *pb = &a; // 错误

       ● 如果函数的形参是指向非const型变量的指针,实参只能用指向非const变量的指针,而不能用指向const变量的指针,这样,在执行函数的过程中可以改变形参指针变量所指向的变量(也就是实参指针所指向的变量)的值。

1
2
3
4
5
void f(Time *pt);
Time *p1;
const Time*p2;
f(p1); // 正确
f(p2); // 错误

       ● 基本规则:希望在调用函数时对象的值不被修改,就应当把形参定义为指向常对象的指针变量,同时用对象的地址作实参(对象可以是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
class Time
{
public:
Time(int,int,int);
int hour;
int minute;
int sec;
};
Time::Time(int h,int m,int s)
{
hour = h;
minute = m;
sec = s;
}
void fun1(Time &t) // t 是对象引用
{ t.hour = 18; }
void fun2(const Time &t) // t 为常引用
{ t.hour = 18; // 错误 }
int main()
{
void fun1(&);
void fun2(const Time &);
Time t1(10,13,56);
fun(t1);
cout<<t1.hour<<endl;
return 0;
}

       非常对象和常对象的比较

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
#include<iostream.h>
class Sample
{
public:
int m;
Sample(int i,int j){ m=i; n=j;}
void setvalue(int i){ n=i; }
void disply()
{
cout<<"m="<<m<<endl;
cout<<"n="<<n<<endl;
}
private:
int n;
};
int main()
{
Sample a(10,20); //若为:const Sample a(10,20);
a.setvalue(40);//不能修改常对象的数据成员
a.m=30; //不能修改常对象的数据成员
a.disply();//常对象不能调用普通成员函数
return 0;
}

const型数据的小结

1
2
3
const Time t = Time(1,2,3);
const int a = 10;
int const a = 10;

       ● t是常对象,其成员值在任何情况下都不能被改变。
       ● a 是常变量,其值不能被改变

1
void Time::fun() const;

       fun 是Time类的常成员函数,可以调用该函数,但不能修改本类中的数据成员(非mutable)

1
2
Time * const pt;
int * const pa;

       ● pt 是指向Time对象的常指针
       ● pa 是指向整数的常指针。指针值不能改变

1
2
const Time *pt;
const int *pa;

       ● pt是指向Time类常对象的指针
       ● pa是指向常整数的指针,不能通过指针来改变指向的对象(值)

文章目录
  1. 1. const 对象的一般形式
  2. 2. 限定作用
  3. 3. mutable
  4. 4. 常对象成员
    1. 4.1. 常数据成员
    2. 4.2. 常成员函数
    3. 4.3. 常成员的使用
  5. 5. 指向常对象的指针变量
    1. 5.1. 指向常对象的指针变量的一般形式
    2. 5.2. 关于指向常对象的指针变量的说明
  6. 6. 对象的常引用
  7. 7. const型数据的小结