const 和 volatile 在实例成员函数的应用
const
和 volatile
的使用范围几乎没有限制
实例成员函数的参数后面可以出现 const
或 volatile
,它们都用于修饰函数隐含参数 this 指向的对象
实例函数对象的参数表后面出现 const
说明this
所指向的对象是不能修改的只读对象
但是可以修改this所指向对象的非只读类型的静态数据成员
实例函数成员参数表后出现const
, volatile
,const volatile
,如果这些实例函数对象隐含参数this
的修饰词不同,则可视为重载函数
调用实例函数成员,编译器会将实参的类型同this
的类型匹配,从而调用最适合的实例函数成员
可读/写的普通变量或者对象应该调用参数表后不带 const
或者 volatile
的实例函数成员
const
对象则应该调用参数表后 带 const
的实例函数成员
volatile
对象应该调用参数表后带 volatile
的实例成员函数
注意,如果调用的时候不存在对应的实例函数成员,会报错
我们来看一个例子,这个例子都是匹配的调用对应的函数
#include<iostream>
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();
}
最后的结果如下:
我们来分析一下上面的四个函数成员 f(), 这四个函数成员为重载函数,它们的显示参数表没有定义任何形参,但是隐含形参this
的类型各不相同,this
用于指向当前函数得对象。
我们来深入思考一下,如果没有最完美得匹配,编译器会退而求其次调用次匹配的函数吗?
看下面的代码,我把 fun() const 和 fun() volatile 都注释,看看情况会怎么改变
#include<iostream>
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 A x(6)
和 volatile A y(6)
由于找不到最合适的匹配函数,都调用了 f() const volatile
我们再来看一个代码,只注释掉 f() const volatile 函数 ,看看如何
#include<iostream>
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();
}
发现
报错原因
我们在刚刚的基础上再把 f() const 注释调用
#include<iostream>
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();
}
我们来看看报错如何
我们最后进行一个实验,只把 f() 函数注释掉,看看会发生什么
#include<iostream>
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
> const volatile
我来解释一下,如果一个对象不含 const
以及 volatile
,那么会优先调用不含const
和 volatile
的函数,如果没有,就去调用 f() const
或者 f() volatile
之一,这里如果两个都存在,编译器不知道调用哪一个,就会报错,如果 f() const
或者 f() volatile
都不存在,才调用f() const volatile
如果对象是 const
类型的也是同样的道理,先去找f() const
,找不到才调用 f() const volatile
且补充一个小点,const
和 volatile
不能出现在构造函数或析构函数的参数表后,因为构造或者析构一个实例对象的时候,对象必须是可以修改的,且必须处于稳定状态(volatile 说明是易变对象)
发布评论