定义类的成员函数
尽管所有成员都必须在类的内部声明,但是成员函数体可以定义在类的内部也可以定义在类外。
定义在类的内部的函数隐式inline函数。
引入this
成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象。当我们调用一个成员函数时,用请求该函数的对象地址初始化this。例如,如果调用
total.isbn()
则编译器负责把total的地址传给isbn的隐式参数this,可以等价地认为编译器将该调用重写为下面的形式:
//伪代码
Sales_data::isbn(&total)
其中,调用Sales_data的isbn成员时传入了total的地址。
因为this的目的总是指向“这个”对象,所以this是一个常量指针。
引入const成员函数
std:string isbn() const {return bookNo;}
紧随参数列表之后的const关键字,这里,const关键字的作用是修饰隐式this指针的类型。
默认情况下,this的类型是指向类类型非常量版本的常量指针。例如在Sales_data成员函数中,this的类型是Sales_data *const。尽管this是隐式的,但它仍然需要遵循初始化规则,意味着(在默认情况下)我们不能把this绑定到一个常量对象上去。这一情况也就使得我们不能在一个常量对象上调用普通的成员函数。
如果isbn是一个普通函数而且this是一个普通的指针参数,则我们应该把this声明为const Sales_data *const。毕竟,在isbn函数体内不会改变this所指的对象,所以把this设置为直线常量的指针有助于提高函数的灵活性。
然而,this是隐式的并且不会出现在参数列表中,所以在哪儿将this声明成指向常量的指针就成为我们必须面对的问题。C++的做法是允许把const关键字放在成员函数的参数列表之后,此时,紧跟在参数列表之后的const表示this是一个指向常量的指针。
像这样使用const的成员函数被称作为常量成员函数(const member function)
可以把isbn的函数体想成这样
//伪代码,说明隐式的this指针是怎么工作的
//this是一个指向常量的指针,因为isbn是一个常量成员
std::string Sales_data::isbn(const Sales_data *const this)
{ return this->bookNo;}
常量对象,常量对象的引用或指针都只能调用常量成员函数。
任何不会修改数据成员的函数都应该声明为const类型。
const类对象只能调用被声明为const的成员函数,而普通的类对象可以调用非const或const成员函数
小结
1)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;
2)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;
3)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应心可能将该成员函数声明为const 成员函数。
补充:const限定符
cosnt限定符修饰的变量,试图修改该变量的值都被编译器视为错误。
除了两种例外情况(将在const章节和类型转换和继承中介绍,c++ primer 5th,p47),指针的类型和其所指向对象的类型必须匹配。
在初始化的过程中,不在乎类型是否为const,因为不会改变该对象。
const默认只在文件内有效,在多个文件中共享const对象,需要在变量定义和声明时都加上extern。
不允许一个非常量引用指向一个常量对象
const int ci = 1024;
int &r2 =ci; //错误,r2为非常量引用,ci为常量对象
允许用任意表达式作为初始值,初始化常量引用,只要该表达式可的结果可以装换成引用的类型。
int i =42;
const int &r1 = i;
const int &r2 = 42;
const int &r3 = r1*2;
int &r4 = r1*2; //错误不允许让一个普通的非常量引用指向一个常量对象
对于指针也类似,只不过指针是对象,多一些内容
指向常量的指针(pointer to const)不能改变所指向的对象的值。
想要存放常量对象的地址,只能使用指向常量的指针(这就是为什么对于定义常量成员函数,因为常量对象调用成员函数,我们需要将this声明为指向常量的指针,也就有了常量成员函数)。
const double pi = 3.14;
double *ptr = π //错误,ptr是普通的非常量指针,不能存放常量对象的地址
const double *cptr = π //正确
与引用类似的的一种例外
允许一个指向常量的指针指向一个非常量对象。
double dval = 3.14;
cptr = &dval。