常类型:使用类型修饰符const说明的类型,常类型的变量或对象成员的值在程序运行期间是不可改变的。
3.10.1 常引用
如果在说明引用时用const修饰,则被说明的引用为常引用。如果用常引用做形参,便不会产生对实参
的不希望的更改。常引用的说明形式如下:
const 类型 &引用名;
例如:int a=5;
const int &b=a;
其中,b是一个常引用,它所引用的对象不允许更改。如果出现:b=12 //则是非法的
在实际应用中,常引用往往用来作形参,这样的参数称为长形参
例 3.39 常引用作函数的参数 */ #include<iostream> using namespace std; int add(const int &,const int &); //声明add的形参是常引用 int main() { int a=20; int b=30; cout<<a<<"+"<<b<<"="<<add(a,b)<<endl; a = 15; //在add函数外,实参是可以改变的 b = 50; //在add函数外,实参是可以改变的 cout<<a<<"+"<<b<<"="<<add(a,b)<<endl; return 0; } int add(const int &i,const int &j) //常引用作函数形参 { //i=i+20; //不允许改变i的值 return i+j; } /* 程序运行结果: 20+30=50 15+50=65 说明:由于add函数两个形参都定义为常引用,所以在函数中不能改变i和j的值,如果改变它们的 值,编译将会出错,如本程序中执行的函数add加有注释的语句"i=i+20;",将会出现编译 错误。因此,用常引用作形参,能够避免对是实参的更改,保证了数据的安全性。 */
3.10.2 常对象
如果说明对象时用常引用const修饰,则被说明的对象为常对象。常对象的数据成员值在
在对象的整个生存周期内不能被改变。常对象的说明形式如下:
类名 const &对象名[(参数表)]
或 const 类名 &对象名[(参数表)]
在定义对象时必须被初始化,而且不能被更新。
例 3.40 非常对象和常对象的比较 */ #include<iostream> using namespace std; class Sample{ public: Sample(int m,int n) { i = m; j = n; } int j; void setvalue(int x) { i = x; } void show() { cout<<"i="<<i<<endl; cout<<"j="<<j<<endl; } private: int i; }; int main() { Sample s(10,20); //对象s是普通对象,而不是常对象 s.setvalue(30); s.j=40; s.show(); //运行结果是 i=30 j=40 /* Sample const s(10,20); //对象s是常对象 s.setvalue(30); //运行错误,C++不允许间接的更改i的值 s.j=40; //运行错误,C++不允许置接的更改j的值 s.show(); //运行错误,C++不允许常对象调用普通的 */ return 0; }
3.10.3 常对象成员
1. 常数据成员
类的数据成员可以是常量或常引用,使用const说明的数据成员称为常数据成员。如果在
一个类中说明了常数据成员,那么构造函数就只能通过成员初始化列表对该数据成员进行
初始化,而其他人任何函都不能对该成员赋值。
例3.41 常数据成员的使用 */ #include<iostream> using namespace std; class Date{ public: Date(int y,int m,int d); void show(); private: const int year; //常数据成员 const int month; //常数据成员 const int day; //常数据成员 }; Date::Date(int y,int m,int d):year(y),month(m),day(d){} //采用成员初始化列表,对数据成员进行初始化 void Date::show() { cout<<year<<"."; cout<<month<<"."; cout<<day<<endl; } int main() { Date date1(2015,5,7); Date date2(2015,5,8); date1.show(); date2.show(); return 0; } /* 运行结果为:2015.5.7 2015.5.8 该程序中定义了如下3个常数据成员: const int year; //常数据成员 const int month; //常数据成员 const int day; //常数据成员 其中year、month、day是int类型的数据成员。需要注意到是构造函数的格式如下: Date::Date(int y,int m,int d):year(y),month(m),day(d){} 其中,冒号后面是一个成员初始化列表,它包含3个初始化项。这是由于year、month、 和day都是常数据成员,C++规定只能通过构造函数的初始化列表对常数据成员进行初始化。 在函数体中采用赋值语句对数据成员直接赋初值是非法的。如以下形式的构造函数是错误的: Date::Date(int y,int m,int d) { year = y; //非法 month = m; //非法 day = d; //非法 } 一旦对某对象的常数据成员初始化后,该数据成员的值是不能改变,但不同对象中的该数据成员 的值可以是不同的(在定义对象时给出) 如: Date date1(2015,5,7); Date date2(2015,5,8); */
2、常成员函数
在类中使用关键字const说明的成员函数为常成员函数,常成员函数的说明格式如下:
类型说明符 函数名(参数表) const;
const是函数类型的一个组成部分,因此在声明函数和定义函数时都要用关键字const,
在调用时不必加const。
例3.42 常成员函数的使用 */ #include<iostream> using namespace std; class Date{ public: Date(int y,int m,int d); void show(); //声明普通的成员函数show() void show() const; //声明常成员函数show() private: const int year; //常数据成员 const int month; //常数据成员 const int day; //常数据成员 /* int year; //普通数据成员 int month; //普通数据成员 int day; //普通数据成员 */ }; Date::Date(int y,int m,int d):year(y),month(m),day(d){} //定义构造函数,采用成员初始化列表, //对数据成员进行初始化 void Date::show() //定义普通的成员函数show() { cout<<"Date::show1()"<<endl; cout<<year<<"."; cout<<month<<"."; cout<<day<<endl; } void Date::show() const //定义常成员函数show() { cout<<"Date::show2()"<<endl; cout<<year<<"."; cout<<month<<"."; cout<<day<<endl; } int main() { Date date1(2015,5,7); //定义普通对象date1 date1.show(); //调用普通的成员函数show const Date date2(2015,5,8); //定义常对象date2 date2.show(); //调用常成员函数show return 0; } /* 程序运行结果如下: Date::show1() 2015.4.7 Date::show2() 2015.4.8 本程序中,类Date中说明了两个同名成员函数show,一个是普通成员函数,另一个是常成员函数, 它们是重载的。可见,关键字const可以被用于区分重载函数。
说明:
1、常成员函数可以访问常数据成员,也可以访问普通数据成员。常数据成员可以被常成员函数访问,
也可以被普通成员函数访问。
2、如果将一个对象说明为常对象,则通过该对象只能调用它的常成员函数,而不能调用普通的成员
函数。常成员函数是常对象唯一的的对外接口,这时C++从语法上对常对象的保护。
表3.2 常成员函数和普通成员函数的访问特性比较
---------------------------------------------------------------------------------------------------------------
数据成员 | 普通成员函数 | 常成员函数
---------------------------------------------------------------------------------------------------------------
普通数据成员 可以访问,也可以改变值 可以访问,但不可以改变值
常数据成员 可以访问,但不可以改变值 可以访问,但不可以改变值
常对象的数据成员 不允许访问和改变值 可以访问,但不可以改变值
3、常成员函数不能更新对象的数据成员,也不能调用该类中的普通成员函数,这就保证了在常成员
函数中绝对不会更新数据成员的值。