c++ const对象与const函数

本文主要讨论c++中const修饰的常对象与没有const修饰的普通对象中的成员函数返回值的常性问题,其中成员函数包括有const修饰和没有const修饰(因为const在成员函数中能形成重载所以能并存),成员变量包括普通变量,指针变量与对象

1 类中的成员变量为普通变量

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int d = 0):data(d){}
	~Base(){}
	
	// 返回值为成员数据的值,有const形成常函数重载
	int GetVal() { return data;}
	int GetVal()const{ return data; } 

	// 返回值为成员数据的引用,有const形成常函数重载
	int& GetRef(){ return data; }
	// 常函数不能修改data的值,以引用返回时为保证data引用空间不被修改,
	// 要用const修饰返回值
	const int& GetRef()const{ return data; }

	// 返回值为成员数据的地址,有const形成常函数重载
	int* GetPtr(){ return &data; }
	// 常函数不能修改data的值,返回data的地址时为保证data的值不被修改,
	// 要用const修饰 *,即不能通过指针的解引用去改变data的值
	const int* GetPtr()const{ return &data; }

private:
	int data;
};
int main()
{
	Base base1(10); // 普通对象
	const Base base2(100); // 常对象

	int a1 = base1.GetVal();
	// base1.GetVal()返回的是一个临时对象,具有常性,即const int tmp
	// 当用引用绑定这个具有常性的空间时,要用const修饰引用
	const int &aref1 = base1.GetVal();

	int a2 = base2.GetVal();
	// base2.GetVal()返回的是一个临时对象,具有常性,即const int tmp
	// 当用引用绑定这个具有常性的空间时,要用const修饰引用
	const int &aref2 = base2.GetVal();

	// 直接返回非常对象的引用,没有常性
	int b1 = base1.GetRef();
	int &bref1 = base1.GetRef();
	const int &bref1_ = base1.GetRef();

	int b2 = base2.GetRef();
	// 直接返回常对象的引用,有常性,要用const修饰
	const int &bref2 = base2.GetRef();

	int* p1 = base1.GetPtr();
	// 返回一个临时的指针变量p,具有常性,即 int *const tmp;
	// 要用const修饰引用指针
	int* const &pref1 = base1.GetPtr();

	// 常对象的数据成员具有常性,不能通过指针改变其值
	const int *p2 = base2.GetPtr();
	// 常对象返回的临时指针,具有双重常性,用引用绑定时,要用双重const修饰
	const int* const &pref2 = base2.GetPtr();

	system("pause");
	return 0;
}

2 类中的成员变量为指针变量

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
	Base(int d = 0) :ptr(new int(d)){}
	~Base(){}

	int* GetVal() { return ptr; }
	int* GetVal()const{ return ptr; }

	int* & GetRef(){ return ptr; }
	// 返回一个指针,但是指针是以引用的方式返回
	// 由于是const方法,要用const修饰引用
	int* const &  GetRef()const{ return ptr; }

	int** GetPtr(){ return &ptr; }
	// ptr是指针,且为常量,const修饰的是二级指针的值
	int*const* GetPtr()const{ return &ptr; }

private:
	int *ptr;
};
int main()
{
	Base base1(10);
	const Base base2(100); 

	int* p1 = base1.GetVal();
	int* const &pref1 = base1.GetVal();

	int* p2 = base2.GetVal();
	int* const &pref2 = base1.GetVal();

	int* refp1 = base1.GetRef();
	int* &refp1_ = base1.GetRef();

	int*  refp2 = base2.GetRef();
	int*  const &refp2_ = base2.GetRef();

	int** pd1 = base1.GetPtr();
	// pdref1绑定临时变量的空间,有常性
	int** const &pdref1 = base1.GetPtr();

	int*const* pd2 = base2.GetPtr();
	// *pdref2 = ptr 有常性
	// pdref2绑定临时变量的空间,有常性
	int*const* const &pdref2 = base1.GetPtr();


	system("pause");
	return 0;
}

3 类中的成员变量为对象

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

class Int
{
public:
	Int(int d = 0) :data(d){}
	~Int(){}
private:
	int data;
};

class Base
{
public:
	Base(int d = 0) :data(d){}
	~Base(){}

	Int GetVal(){ return data; }
	Int GetVal()const{ return data; }

	Int& GetRef(){ return data; }
	const Int& GetRef()const { return data; }

	Int* GetPtr(){ return &data; }
	const Int* GetPtr()const{ return &data; }

private:
	Int data;
};
int main()
{
	Base base1(10);
	const Base base2(100);

	Int a1 = base1.GetVal();
	// 区别于类中成员为内置类型,当成员为对象时,调用拷贝构造函数
	// 这里不会返回临时对象,不具有常性
	Int &aref1 = base1.GetVal();

	Int a2 = base2.GetVal();
	// 区别于类中成员为内置类型,当成员为对象时,调用拷贝构造函数
	// 这里不会返回临时对象,不具有常性
	Int &aref2 = base2.GetVal();

	Int b1 = base1.GetRef();
	Int& refb1 = base1.GetRef();

	Int b2 = base2.GetRef();
	const Int&  refb2 = base2.GetRef();

	Int *p1 = base1.GetPtr();
	Int* const &pref1 = base1.GetPtr();

	const Int* p2 = base2.GetPtr();
	const Int* const &pref2 = base2.GetPtr();

	system("pause");
	return 0;
}

总结:判断返回值是否具有常性,要注意一下几点
1、const对象的成员数据具有常性
2、当返回指针或引用时,要考虑指针所指向空间的常性和引用所绑定空间的常性
3、const成员方法不能修改成员变量的值
4、以临时变量返回具有常性
5、当返回对象时,调用的是拷贝构造函数,不会返回临时变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值