常对象、常指针、常引用

公用数据的保护

  • C++虽然采取了不少有效的措施(如设private保护)以增加数据的安全性,但是有些数据却往往是共享的,例如实参与形参,变量与引用,数据及其指针等,人们可以在不同的场合通过不同的途径访问同一个数据对象。有时在无意之中的误操作会改变有关数据的状况,而这是人们所不希望出现的。
  • 既要使得数据能在一定范围内共享,又要保证它不被任意修改,这时可以使用const,即把有关的数据定义为常量。

常对象

  • 可以在定义对象时加关键字const,指定对象为常对象。常对象必须要有初值,如:Time const t1(12, 34, 46); //定义t1是常对象。这样,在t1的生命周期中,对象t1中的所有数据成员的值都不能被修改。
  • 定义常对象的一般形式为:类名 const 对象名[(实参表)];,也可以把const写在最左面:const 类名 对象名[(实参表)];。二者等价。
    在定义常对象时,必须同时对之初始化,之后不能再改变。

说明:

  • 如果一个对象被声明为常对象,则通过该对象只能调用它的常成员函数,而不能调用该对象的普通成员函数(除了由系统调用的隐式的构造函数和析构函数)。常对象成员函数是常对象唯一的对外接口。
    例如:(❌)
const Time t1(10, 15, 36); //定义常对象t1
t1.get_time(); //试图调用常对象t1中的普通成员函数,非法

引用常对象中的数据成员需将该成员函数声明为const即可。例如:void get_time(); //将函数声明为const。这表明get_time是一个const型函数,即常成员函数

  • 常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值
  • 有时在编程时有要求,一定要修改常对象成员中某个数据成员的值(例如一个类中有一个用于计数的变量count,其值应当能不断变化),C++考虑到实际编程的需要,对此作了特殊的处理,对该数据成员声明为mutable,如mutable int count;。把count声明为可变的数据成员,这样就可以用声明为const的成员函数来修改它的值

常对象成员

  • 可以将对象的成员声明为const,包括常数据成员和常成员函数

常数据成员

  • 其作用和用法与一般常变量相似,用关键字const来声明常数据成员。常数据成员的值是不能改变的。只能通过构造函数的参数初始化表来对常数据成员进行初始化,任何其他函数都不能对常数据成员赋值
  • 如在类体中定义了常数据成员hour:const int hour; //定义hour为常数据成员,如果在类外定义构造函数,应写成以下形式:Time::Time(int h):hour(h){} //通过参数初始化表对常数据成员hour初始化

常成员函数

  • 一般的成员函数可以引用本类中的非const数据成员,也可以修改它们。如果成员函数被声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们
    如:void get_time() const; //注意const的位置在函数名和括号之后
  • 声明常成员函数的一般形式为:`类型名 函数名(参数表) const
  • const为函数类型的一部分,在声明函数和定义函数时都要有const关键字,在调用时不必加const。常成员函数可以引用const数据成员,也可以引用非const的数据成员。const数据成员可以被const成员函数引用,也可以被非const的成员函数引用

怎样利用常成员函数呢?

  1. 如果在一个类中,有些数据成员的值允许改变,另一些数据成员的值不允许改变,则可以将一部分数据成员声明为const,以保证其值不被改变,可以用非const的成员函数引用这些数据成员的值,并修改非const数据成员的值
数据成员非const成员函数const成员函数
非const的普通数据成员可以引用,也可以改变值可以引用,但不可以改变值
const数据成员可以引用,但不可以改变值可以引用,但不可以改变值
const对象不允许可以引用,但不可以改变值
  1. 如果要求所有的数据成员的值都不允许改变,则可以将所有的数据成员声明为const,或将对象声明为const(常对象),然后用const成员函数引用数据成员,这样起到"双保险"的作用,切实保证了数据成员不被修改
  2. 如果已定义了一个常对象,只能调用其中的const成员函数,而不能调用非const成员函数(不论这些函数是否会修改对象中的数据)。这是为了保证数据的安全。如果需要访问对象中的数据成员,可将常对象中的所有成员函数都定义为const成员函数,并确保在函数中不修改对象中的数据成员
  • 不要误认为常对象中的成员函数都是常成员函数。常对象只保证其数据成员是常数据成员,其值不被修改。如果在常对象中的成员函数未加const声明,编译系统把它作为非const成员函数处理。
  • 还有一点要指出,常成员函数不能调用另一个非const成员函数。

指向对象的常指针

  • 将指针变量声明为const型,这样的指针变量始终保持为初值,不能改变,即其指向不变
    如:
Time t1(10, 12, 15), t2; //定义对象
Time* const ptr1; //const位置在指针变量名前面,指定ptr1是常指针变量
ptr1 = &t1; //ptrl指向对象t1,此后不能再改变指向
ptr1 = &t2; //错误,ptr1不能改变指向
  • 定义指向对象的常指针变量的一般形式为:类名 * const 指针变量名;
  • 注意:指向对象的常指针变量的值不能改变,即始终指向同一个对象,但可以改变其所指向对象的值
  • 如果想将一个指针变量固定地与一个对象相联系(即该指针变量始终指向一个对象),可以将它指定为const型指针变量。这样可以防止误操作,增加安全性
  • 往往常指针作为函数的形参,目的是不允许在函数执行过程中改变指针变量的值,使其始终指向原来的对象。如果在函数执行过程中修改了该形参的值,编译系统就会发现错误,给出出错信息,这样比人工来保证形参值不被修改更可靠

指向常对象的指针变量

  • 定义指向常变量地指针变量的一般形式为:const 类型名 * 指针变量名;

说明

  1. 如果一个变量已被声明为常变量,只能用指向常变量的指针变量指向它,而不能用一般的(指向非const型变量的)指针变量指向它

对象的常引用

  • 一个变量的引用就是变量的别名。实际上,引用是一个指针常量,用来存放该变量的地址。如果形参为变量的引用,实参为变量名,则在调用函数进行虚实结合时,把实参变量的地址传给形参(引用),这样引用就指向实参变量。对象的引用也是与此类似的。也可以把引用声明为const,即常引用。

例:对象的引用和常引用

#include<iostream>
using namespace std;
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 fun(Time& t) //形参t是Time类对象的引用
{
	t.hour = 18;
}

int main()
{
	Time t1(10, 13, 56); //t1是Time类对象
	fun(t1); //实参是Time类对象,可以通过引用来修改实参t1的值
	cout << t1.hour << endl; //输出t1.hour的值为18
	return 0;
}

如果不希望在函数中修改实参t1的值,可以把fun函数的形参t声明为const(常引用),函数fun的首行为void fun(const Time &t);。这样在函数中就不能改变t所代表的实参t1的值。注意:不是不能改变"引用t"的指向,而是t所指向的变量的值。

  • 在C++面向对象程序设计中,经常用常指针和常引用作函数参数。注意既能保证数据安全,使数据不能被随意修改,在调用函数时又不必建立实参的拷贝。

const型数据的小结

形式含义
Time const t;t是常量,其值在任何情况下都不能改变
void Time::fun() constfun是Time类中的常成员函数,可以引用,但不能修改本类中的数据成员
Time * const p;p是指向Time类对象的常指针变量,p的值(p的指向)不能改变
const Time * p;p是指向Time类对象的指针变量,p指向的类对象的值不能通过p来改变
const Time &t1=t;t1是Time类对象t的引用,二者指向同一存储空间,t的值不能改变
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值