常类型(C++学习笔记 30)

因为程序中各种形式的数据共享,在不同程度上破坏了数据的安全性。引入常类型的目的是,为了保证数据共享又防止数据被改动。

常类型是指使用类型修饰符 const 说明的类型,常类型的变量或对象成员的值在程序运行期间是不可改变的。
本文将从三方面入手:常引用、常对象和常对象成员。

一、常引用

  • 常引用: 在说明引用时用 const 修饰的引用。
  • 如果用 常引用作形参,便不会产生对实参的不希望的更改。
  • 常引用的说明形式:
    const 类型 &引用名;
    例如:
int a=5;
const int &b=a;

其中,b 是一个常引用,它所引用的对象不允许更改。如果出现:b=22;则非法。

例 1:常引用作函数参数。

在实际应用中,常引用往往用来作函数的形参,这样的参数称为 常参数
用常引用作形参,能够避免对实参的更改,保证数据的安全。

#include<iostream>
using namespace std;
int add(const int &i,const int &j);  //函数 add 的形参是常引用
int main(){
	int a=20;
	int b=30;
	cout<<a<<"+"<<b<<"="<<add(a,b)<<endl;
	a=15;
	b=50;
	cout<<a<<"+"<<b<<"="<<add(a,b)<<endl;
	return 0;
} 
int add(const int &i,const int &j){
	//i=i+50;  //不允许改变 i 的值,error是 assignment of read-only reference 'i' 即 给只读引用值'i'赋值出现错误 
	return i+j;
} 

二、常对象

  • 常对象:在说明对象时用 const 修饰。
  • 常对象的数据成员值在对象的整个生存期内不能被改变。
  • 常对象的说明形式:
    类名 const 对象名[(参数表)];
    或者
    const 类名 对象名[(参数表)]
    在定义对象时必须进行初始化,而且不能被更新。

例 2:常对象 和 非 常对象 的比较

#include<iostream>
using namespace std;
class Sample{
	public:
		int m;
		Sample(int i,int j){
			m=i;
			n=j;
		}
		void setvalue(int i){
			n=i;
		}
		void display(){
			cout<<"m="<<m<<endl;
			cout<<"n="<<n<<endl;
		}
	private:
		int n;
};
int main(){
	Sample a(10,20);
	a.setvalue(40);
	a.m=30;
	a.display();
	return 0;
}

在例 2 中,对象 a 是一个普通的对象,而不是常对象,执行结果为:
在这里插入图片描述
若将上述的对象 a 定义为常对象,主函数修改一下:

int main(){
	const Sample a(10,20);  //a 是常对象,而不是普通对象 
	a.setvalue(40);	  //错误:不允许改变常对象的数据成员值 
	a.m=30;		//错误:不允许改变常对象的数据成员值 
	a.display();    //错误:不允许常对象调用普通的成员函数 
	return 0;
}

则会出现三处错误(要格外注意,第三处错误,不允许常对象调用普通的成员函数)。

三、常对象成员

1、常数据成员

  • 类的数据成员可以是常量或常引用,使用 const 说明的数据成员称为 常数据成员
  • 如果在一个类中说明了常数据成员,那么构造函数就只能通过成员初始化列表对该数据成员进行初始化,在构造函数的函数体内对常数据成员赋初值也是非法的,而且其他任何函数都不能对该成员赋值。
  • 一旦对某对象的常数据成员初始化后,该数据成员的值是不能改变的,但不同对象中的该数据成员的值可以是不同的(在定义对象时给出)。

例 4:常数据成员的使用。

#include<iostream>
using namespace std;
class Date{
	public:
		Date(int y,int m,int d);
		void showDate();
	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::showDate(){
	cout<<year<<"."<<month<<"."<<day<<endl;
}
int main(){
	Date date1(2018,11,25);
	date1.showDate();
	return 0;
}

2、常成员函数

  • 在类中使用关键字 const 说明的成员函数为常成员函数。
  • 常成员函数的说明格式如下:
    类型说明符 函数名(参数表) const;
    const是函数类型的一个组成部分,因此在声明和定义函数时都要有关键字 const,在调用时不必加 const。

例 5:常成员函数的使用(仔细看代码)。

#include<iostream>
using namespace std;
class Date{
	public:
		Date(int y,int m,int d);
		void showDate();  //声明普通的成员函数 showDate 
		void showDate() const;  //声明常成员函数 showDate 
	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(2018,11,25);  //定义普通对象 date1 
	date1.showDate();
	const Date date2(2018,9,28);  //定义常对象 date2
	date2.showDate();
	return 0;
}

执行结果:
在这里插入图片描述
  在例 5中类 Date 说明了两个同名的成员函数 showDate,一个是普通的成员函数,另一个是常成员函数,它们是重载的(关键字 const 可以被用于区分重载函数)。
  在主函数中说明了两个对象 date1 和 date2,其中对象 date2 是常对象。通过对象 date1 调用的是没有用 const 修饰的成员函数 showDate,而通过对象 date2 调用的是用 const 修饰的常成员函数 showDate。

说明注意:
(1)常成员函数可以访问常数据成员,也可以访问普通数据成员。


数据成员 普通成员函数 常成员函数
普通数据成员 可以访问,也可以改变值 可以访问,但不可以改变
常数据成员 可以访问,但不可以改变值 可以访问,但不可以改变
常对象的数据成员 不允许访问和改变值 可以访问,但不可以改变

(2)如果将一个对象说明为常对象,则通过该对象只能调用它的常成员函数,而不能调用普通的成员函数。所以说,常成员函数是常对象唯一的对外接口,这是C++从语法机制上对常对象的保护。
(3)常成员函数不能更新对象的数据成员,也不能调用该类中的普通成员函数,这就保证了在常成员函数中绝对不会更新数据成员的值。

猜你喜欢

转载自blog.csdn.net/aaqian1/article/details/84502579
c30
30
今日推荐