1. const成员

1.1 const修饰类的成员函数

在Date日期类中,我们实例化一个普通对象。而普通对象调用普通成员函数需要传参,传参传给隐藏的this指针,下面给出一个例子:

代码语言:javascript

AI代码解释

class Date
{
public:
	Date(int year=0, int month=0, int day=0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print() 
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;

};

int main() {
	//这里实例化的是一个普通对象
    Date d(2025, 8, 23);
	
    //此时d(普通对象)调用Print
    //传参给this指针
    //也就是将d1的地址传给了this
    d1.Print();
}

上面这种情况肯定是能够顺利运行的,但是如果实例化一个const对象呢,还能够顺利编译吗?

代码语言:javascript

AI代码解释

int main() {
	const Date d2(2025, 8, 23);
	d2.Print();
}

我们发现报错了:

这是因为将Date实例化为const,那么在调用Print()时,传入的地址类型应该是const Date *,但是this指针是Date的,那么这个转换是不被允许的(因为权限被放大了)

那么我们第一反应的解决方案肯定就是将这类的this指针类型修改成const Date *,但是我们学过这个this指针是由编译器自动生成的,我们没有办法直接修改。所以C++的设计者这样解决:

代码语言:javascript

AI代码解释

//在成员函数参数列表后面加上const修饰
//起作用就相当于void Print(const Date * const this )
//这样一来这个传参过程就能够顺利进行了

void Print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

总结:建议所有不修改成员变量的成员函数都加上const

  • const -> const 权限大小不变
  • 普通 -> const 权限变小(是编译器允许的)

Q:思考下面几个问题

  1. const对象可以调用非const成员函数吗?
  2. 非const对象可以调用const成员函数吗?
  3. const成员函数内可以调用其它的非const成员函数吗?
  4. 非const成员函数内可以调用其它的const成员函数吗?

A:答案

  1. 不能,权限被放大了
  2. 能,权限被缩小了
  3. 不能,权限被放大了
  4. 能,权限被缩小了

2. 取地址及const取地址操作符重载

前面讲到,一共有6个默认成员函数,我们已经学习了4个,现在我们来看一看剩下两个(并不是很重要,默认生成的即可):

代码语言:javascript

AI代码解释

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

总结:这两个运算符一般不需要重载,使用编译器默认生成的取地址重载即可。只有在一些特殊情况才需要重载,例如想要让用户看到指定的信息!


3. 流提取和流插入运算符重载

代码语言:javascript

AI代码解释

Date d2(2025, 8, 23);
cout << d2 << endl;

会报错:

显然我们想要完成自定义类的输入和输出,就要进行流提取、流插入的运算符的重载。

但是我们想一下,内置类型都是可以直接使用流提取和流插入运算符的,这似乎好像也是重载哦!

代码语言:javascript

AI代码解释

int i = 1;
double d = 2.2;
cout << i;//自动识别类型
cout << d;

我们深入了解一下:

coutcin 是全局对象,他们包含在iostream头文件中,所以我们在写C++文件的时候会#include <iostream>。cin是istream的对象,cout是ostream的对象,istream和ostream是库中的流提取和流插入的两个类型

而<<和>>能够识别不同的内置类型的真正原因就是,把所有内置类型都重载了:

所以其实真实的情况就是:

那么针对Date日期类这种自定义类型,我们也只需要重载一下就可以了。

 

更多推荐