【C++】-const对象及成员函数之类和对象中篇完结(中)

💖作者:小树苗渴望变成参天大树
❤️‍🩹作者宣言:认真写好每一篇博客
💨作者gitee:gitee
💞作者专栏:C语言,数据结构初阶,Linux,C++


前言

今天我们来讲讲const对成员对象和成员函数都有那些要注意的细节,还有两个默认成员函数的简单讲解,内容不是特别难,对于const大家要熟悉引用中对于权限的放大,缩小,平移的理解,可以参考这篇引用的第6.5节讲的内容,再来理解这个就好理解一点,那我们开始进入正文的讲解


一、案例的引入

我们其实已经接触过了一点关于const修饰对象的案例了,再讲解输入输出运算符重载的博客中,全局的重载函数访问私有的成员有两种方法,一个使用友元,一个使用共有的成员函数将值返回出来,第二种方法

在这里插入图片描述
我们当时说为什么这个不加const修饰,主要原因是类型的不匹配,对于我们成员函数,我们再类和对象的第一篇博客就讲解到过,每个正常成员函数都有一个隐藏的this指针(有的用static修饰的成员函数就没有this指针,所以这里说正常的成员函数),对于隐藏的this指针他的类型为类名+*+this(以日期类为例:date * this),准确来说,他的类型为(*date const this)修饰的this本身不变修改,当时没说明是怕大家不理解,这里再提出来,对于上图的案例,其实应该写成这样的:
在这里插入图片描述
通过这个图,大家应该差不多明白了为什么上面不加const了吧,大家有了这方面的了解之后,我们再来细看

二、const对象和成员函数

再上面我们如果想传const的对象应该怎么办,this指针本身就是隐藏的,所以没有办法显示的加const,那么祖师爷针对这个问题就规定了再括号后面加一个const,例如:

class Date
{
public:
	Date(int year=1, int month=1, int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << "Print()" << endl;
	}
	void Print() const
	{
		cout << "Print()const" << endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

我们来测试一下:
在这里插入图片描述
我们来看看加const的成员函数能不能调用普通对象:
在这里插入图片描述

因为从Datethis传给const Datethis是权限的缩小,所以可以,反过来就不行,既然这样有的人就像把全部的成员函数都加一个const这样不是更好吗??其实并不是,对于那些不修改对象的成员函数可以加,效果更好,修改自身不可以加

在这里插入图片描述

这个const对象d2无法调用非const的成员函数,原因就是权限的放大了,const对象没有办法传给非const的this

通过上面的案例

  1. const对象不可以调用非const成员函数
  2. 非const对象可以调用const成员函数 **

我们来看看之前写了日期类那些可以加:

class date 
{
public:
	date(int year = 1, int month = 1, int day = 1)//全缺省的构造函数
	{
		if (day > 0 && day <= getmonthday(year, month) && month > 0 && month < 13)
		{
			_year = year;
			_month = month;
			_day = day;
		}
		else
		{
			cout << "非法初始化" << endl;
			assert(false);
		}
	}
	//拷贝构造
	//赋值重载
	//析构函数

	void print()const//当成内联函数
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	bool operator<(const date& d)const;
	bool operator==(const date& d)const;
	bool operator>(const date& d)const;
	bool operator>=(const date& d)const;
	bool operator<=(const date& d)const;
	bool operator!=(const date& d)const;

	date& operator+=(int day);
	date operator+(int day)const;


	static int getmonthday(int year, int month);

	// 日期-天数
	date operator-(int day)const;
	// 日期-=天数
	date& operator-=(int day);

	// 前置++
	date & operator++();
	// 后置++
	date operator++(int);
	// 后置--
	date operator--(int);
	// 前置--
	date& operator--();

	int operator-(const date& d)const;
	int getyear()const
	{
		return _year;
	}
	int getmonth()const
	{
		return _month;
	}
	int getday()const
	{
		return _day;
	}
	friend ostream& operator<<(ostream& cout, const date& d);
	friend istream& operator>>(istream& cin, date& d);

再定义的地方也要加const

不加会出现那些情况:
在这里插入图片描述
大家看这样就比较不了,原因是小于里面的隐藏this不是const修饰类型,而运算符的第一个参数默认传给this的,第二不行的原因是,d2是const修饰类型,传给的this是普通的类型,是权限的放大,所以不行
在这里插入图片描述
所以必须要在小于那里加const:
在这里插入图片描述
所以有的时候不加还是不行的,根据具体实际来写

  1. 要修改成员变量的函数不能加
  2. 只要成员函数内部不修改成员变量都应该加const,这样const对象和普通对象都可以调用

其实对于单个函数需不需要使用const很好判断的,但是对于函数复用,就很麻烦,我们来看看下面两个问题:(这样自己再理解一下日期类那些函数加const的特性)

  1. const成员函数内可以调用其它的非const成员函数吗?
    在这里插入图片描述

  2. 非const成员函数内可以调用其它的const成员函数吗?
    在这里插入图片描述
    大家应该看到想要的结果了吧,在日期类中,我们的小于和等于是自己实现的,其余的都是复用这两个函数,如果这两个不加const,其余的都不能加,加了就会报错。

在这里插入图片描述
只要复用了小于和等于的函数都需要加const,不然就会报错,所以大家在写日期类的时候要主要了,如果有的函数用的时候保存,大概路是类型传参不匹配,往前面检查就行了。这个在后面也会遇到的,现在大家理解起来还是有点困难的。

三、取地址及const取地址操作符重载

我们在类和对象中篇的时候,讲过我们有六个默认成员函数,之前已经讲过了四个,现在还剩两个,这两个几乎很少需要自己实现,默认生成的就可以完成需求,这两个没啥可以讲的,就是取到对象的地址

class Date
{ 
public :
 Date* operator&()
 {
   return this ;
 }
 const Date* operator&()const
 {
 return this ;
 }
private :
 int _year ; // 年
 int _month ; // 月
 int _day ; // 日
};

在这里插入图片描述
const的取地址运算符就是为了取出const对象的地址,这里面有一个注意的细节,我们的d2对象是const修饰的,所以必须初始化,因为只有一次初始化的机会。我这里直接给缺省值,调用构造函数就行了。

自己手写这个函数,可能不想让别人得到对象的地址,返回一个假的数据给他:
在这里插入图片描述
大家知道了解就好,以后开发几乎不咋需要自己实现

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

四、总结

到这里我们的类和对象中篇算是讲解完了,里面的内容非常的多,尤其是细节方面的,大家一定要理解,画图,接下来我将讲解类和对象下篇的知识点,初始化列表是一个比较难的知识点,大家做好准备,我们下篇再见。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘柚!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值