const 和 volatile 在实例成员函数的应用

constvolatile 的使用范围几乎没有限制
实例成员函数的参数后面可以出现 constvolatile,它们都用于修饰函数隐含参数 this 指向的对象
实例函数对象的参数表后面出现 const 说明this 所指向的对象是不能修改的只读对象
但是可以修改this所指向对象的非只读类型的静态数据成员
实例函数成员参数表后出现constvolatileconst volatile ,如果这些实例函数对象隐含参数this的修饰词不同,则可视为重载函数
调用实例函数成员,编译器会将实参的类型同this的类型匹配,从而调用最适合的实例函数成员
可读/写的普通变量或者对象应该调用参数表后不带 const 或者 volatile的实例函数成员
const对象则应该调用参数表后 带 const 的实例函数成员
volatile对象应该调用参数表后带 volatile 的实例成员函数
注意,如果调用的时候不存在对应的实例函数成员,会报错


我们来看一个例子,这个例子都是匹配的调用对应的函数

#include
using namespace std;
class A {
	int a;
	const int b;
public:
	int f() {
		cout << "f() " << endl;
		a++;
		//b++;  不可修改
		return a;
	}
	int f()volatile {
		cout << "volatile f()" << endl;
		a++;   // 可以修改本类实例成员数据成员 volatile int a
		//b++;
		return a;
	}
	int f() const volatile {
		cout << "f() const volatile " << endl;
		// a++; 也是错误的
		return a;
	}
	int f()const  {
		cout << "f() const " << endl;
		// a++ ;也是错误的
		return a;
	}
	A(int x) :b(x) {
		a = x;
	}
};
A w(3);  // 这是一个可写对象
const A x(6);  // 这是一个可读对象
volatile A y(6);  // 定义易变对象
const volatile A z(8); // 定义可读易变对象
int main() {
	w.f();
	x.f();
	y.f();
	z.f();
}

最后的结果如下:
const 和 volatile 在实例成员函数的应用_第1张图片

我们来分析一下上面的四个函数成员 f(), 这四个函数成员为重载函数,它们的显示参数表没有定义任何形参,但是隐含形参this的类型各不相同,this用于指向当前函数得对象。


我们来深入思考一下,如果没有最完美得匹配,编译器会退而求其次调用次匹配的函数吗?
看下面的代码,我把 fun() const 和 fun() volatile 都注释,看看情况会怎么改变

#include
using namespace std;
class A {
	int a;
	const int b;
public:
	int f() {
		cout << "f() " << endl;
		a++;
		//b++;  不可修改
		return a;
	}
	//int f()volatile {
	//	cout << "volatile f()" << endl;
	//	a++;   // 可以修改本类实例成员数据成员 volatile int a
	//	//b++;
	//	return a;
	//}
	int f() const volatile {
		cout << "f() const volatile " << endl;
		// a++; 也是错误的
		return a;
	}
	//int f()const  {
	//	cout << "f() const " << endl;
	//	// a++ ;也是错误的
	//	return a;
	//}
	A(int x) :b(x) {
		a = x;
	}
};
A w(3);  // 这是一个可写对象
const A x(6);  // 这是一个可读对象
volatile A y(6);  // 定义易变对象
const volatile A z(8); // 定义可读易变对象
int main() {
	w.f();
	x.f();
	y.f();
	z.f();
}

运行结果如下
const 和 volatile 在实例成员函数的应用_第2张图片
我们看的出来,const A x(6)volatile A y(6) 由于找不到最合适的匹配函数,都调用了 f() const volatile


我们再来看一个代码,只注释掉 f() const volatile 函数 ,看看如何

#include
using namespace std;
class A {
	int a;
	const int b;
public:
	int f() {
		cout << "f() " << endl;
		a++;
		//b++;  不可修改
		return a;
	}
	int f()volatile {
		cout << "volatile f()" << endl;
		a++;   // 可以修改本类实例成员数据成员 volatile int a
		//b++;
		return a;
	}
	//int f() const volatile {
	//	cout << "f() const volatile " << endl;
	//	// a++; 也是错误的
	//	return a;
	//}
	int f()const  {
		cout << "f() const " << endl;
		// a++ ;也是错误的
		return a;
	}
	A(int x) :b(x) {
		a = x;
	}
};
A w(3);  // 这是一个可写对象
const A x(6);  // 这是一个可读对象
volatile A y(6);  // 定义易变对象
const volatile A z(8); // 定义可读易变对象
int main() {
	w.f();
	x.f();
	y.f();
	z.f();
}

发现
const 和 volatile 在实例成员函数的应用_第3张图片
报错原因
在这里插入图片描述


我们在刚刚的基础上再把 f() const 注释调用

#include
using namespace std;
class A {
	int a;
	const int b;
public:
	int f() {
		cout << "f() " << endl;
		a++;
		//b++;  不可修改
		return a;
	}
	int f()volatile {
		cout << "volatile f()" << endl;
		a++;   // 可以修改本类实例成员数据成员 volatile int a
		//b++;
		return a;
	}
	//int f() const volatile {
	//	cout << "f() const volatile " << endl;
	//	// a++; 也是错误的
	//	return a;
	//}
	//int f()const  {
	//	cout << "f() const " << endl;
	//	// a++ ;也是错误的
	//	return a;
	//}
	A(int x) :b(x) {
		a = x;
	}
};
A w(3);  // 这是一个可写对象
const A x(6);  // 这是一个可读对象
volatile A y(6);  // 定义易变对象
const volatile A z(8); // 定义可读易变对象
int main() {
	w.f();
	x.f();
	y.f();
	z.f();
}

我们来看看报错如何
const 和 volatile 在实例成员函数的应用_第4张图片
在这里插入图片描述


我们最后进行一个实验,只把 f() 函数注释掉,看看会发生什么

#include
using namespace std;
class A {
	int a;
	const int b;
public:
	//int f() {
	//	cout << "f() " << endl;
	//	a++;
	//	//b++;  不可修改
	//	return a;
	//}
	int f()volatile {
		cout << "volatile f()" << endl;
		a++;   // 可以修改本类实例成员数据成员 volatile int a
		//b++;
		return a;
	}
	int f() const volatile {
		cout << "f() const volatile " << endl;
		// a++; 也是错误的
		return a;
	}
	int f()const  {
		cout << "f() const " << endl;
		// a++ ;也是错误的
		return a;
	}
	A(int x) :b(x) {
		a = x;
	}
};
A w(3);  // 这是一个可写对象
const A x(6);  // 这是一个可读对象
volatile A y(6);  // 定义易变对象
const volatile A z(8); // 定义可读易变对象
int main() {
	w.f();
	x.f();
	y.f();
	z.f();
}

发现报错如下
const 和 volatile 在实例成员函数的应用_第5张图片


总结一下,总的一个优先级如下:
啥都没有 > constvolatile > const volatile
我来解释一下,如果一个对象不含 const 以及 volatile ,那么会优先调用不含constvolatile 的函数,如果没有,就去调用 f() const 或者 f() volatile 之一,这里如果两个都存在,编译器不知道调用哪一个,就会报错,如果 f() const 或者 f() volatile 都不存在,才调用f() const volatile
如果对象是 const 类型的也是同样的道理,先去找f() const ,找不到才调用 f() const volatile

且补充一个小点,constvolatile 不能出现在构造函数或析构函数的参数表后,因为构造或者析构一个实例对象的时候,对象必须是可以修改的,且必须处于稳定状态(volatile 说明是易变对象)

你可能感兴趣的:(c++,c++)