简介
this 指针
- 每个成员函数都有一个额外的、隐含的形参–this指针,这个指针指向的是调用函数的对象的地址。(除了在12.6节介绍的static成员函数外)
const 成员函数
定义类时,声明的成员函数后面有一个const——const 成员函数。
这个const所起的作用:const改变了隐含的this 形参的类型。
用这种方式使用const的函数称为常量成员函数。由于this是指向const对象的指针,const成员函数不能修改调用该函数的对象。因此,函数avg_price和函数same_isbn只能读取而不能修改调用他们的对象的数据成员。
在类的定义外面定义成员函数必须指明它们是类的成员!
* double Sale_item::avg_price() *
默认构造函数
对于具有类类型的成员,如string类型的isbn ,则会调用该成员所属类自身的默认构造函数实现初始化,初始化为空串;
内置类型成员的初值依赖于对象如何定义,如果对象在全局作用域中定义(即不在任何函数中)或定义为静态局部对象,则这些成员将被初始化为0。
如果对象在局部作用域中定义,则这些成员没有初始化。
===============================================================================================================================
一、类的成员函数
1、成员函数的定义
成员函数也包含以下四个部分:
- 函数返回类型;
- 函数名
- 用逗号隔开的形参表(可能是空的);
- 包含在一对花括号里面的函数体。
前面三部分组成函数原型,函数原型定义了所有和函数相关的类型信息:函数返回类型是什么、函数的名字、应该给这个函数传递什么类型的实参。
函数原型必须在类中定义。
函数体则既可以在类中也可以在类外定义。
class Sale_item{
public:
double avg_price() const;//函数声明,形参表为空,返回double类型的值,const说明这是一个const成员函数
bool same_isbn(const Sale_item &rhs) const
//返回bool类型值,有一个const Sale_item类型的引用
{return isbn==rhs.isbn;}
private:
std::string isbn;
unsigned units_sold;
double revenue;
};
二、定义成员函数的函数体
类的所有成员都必须在类定义的花括号里面声明,此后,就不能再为类增加任何成员;
类的成员函数必须如声明的一般定义,类的成员函数既可以在类的定义内定义也可以在类的定义外定义;
编译器隐式地将在类内定义的成员函数当作内联函数;
类的成员函数可以访问该类的private成员。
1、成员函数含有额外的、隐含的形参
调用成员函数需要使用对象来调用。在上面的类定义的基础上。
total.same_isbn(trans);//传递对象trans,使用对象trans初始化rhs,于是,rhs.isbn是trans.isbn的引用。
2、this指针的引入–成员函数隐含的形参
每个成员函数都有一个额外的、隐含的形参–this指针,这个指针指向的是调用函数的对象的地址。(除了在12.6节介绍的static成员函数外)
在本节定义的这个类里边,成员函数 bool same_isbn(const Sale_item &rhs) const 里面就有一个形参this 指针,看下面3 。
total.same_isbn(trans);
就如编译器这样重写这个函数调用:
Sale_item::same_isbn(&total,trans);//在这个调用中,函数same_isbn中的数据成员isbn属于对象total
3、const成员函数的引入
定义类时,声明的成员函数后面有一个const——const 成员函数。
这个const所起的作用:const改变了隐含的this 形参的类型。如下:
因为same_isbn成员函数后面有一个const,所以在调用total.same_isbn(trans)时,隐含的this形参将是一个指向total 对象的const Sale_item * 类型的指针。same_isbn函数可以像如下编写:
bool Sale_item::same_isbn(const Sale_item * const this,//指向某个const对象的const Sale_item * 类型的指针
const Sale_item & rhs)const
{ return (this->isbn == rhs.isbn);}
用这种方式使用const的函数称为常量成员函数。由于this是指向const对象的指针,const成员函数不能修改调用该函数的对象。因此,函数avg_price和函数same_isbn只能读取而不能修改调用他们的对象的数据成员。
const对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试用他们累调用非const成员函数,则是错误的。
4、this 指针的使用
在成员函数中,不必显示地使用this 指针来访问被调用函数所属对象的成员,对这个类的成员的任何没有前缀的引用,都被假定为通过指针this 实现的引用;
由于this 指针是隐式定义的,因此不需要在函数的形参表中包含 this 指针,实际上,这样做是非法的。但是,在函数体中可以显示地使用this 指针。
bool same_isbn( const Sale_item & rhs)const
{ return isbn==rhs.isbn;}//在这个函数中,isbn 的用法与this ->units_sold 或 this ->revenue 的用法一样。
bool same_isbn( const Sale_item & rhs)const
{ return this->isbn==rhs.isbn;}
二、在类外定义成员函数
在类的定义外面定义成员函数必须指明它们是类的成员!!!
double Sale_item::avg_price() const{
if(units_sold)
return revenue/units_sold;
else
return 0;
}
- Sale_item::avg_price() 使用作用域操作符指明函数 avg_price() 是在类Sale_item 的作用域范围内定义的。
形参后面的const则反映了在类Sale_item 中声明成员函数的形式。
在任何函数定义中,返回类型和形参表必须和函数声明(如果有的话)一致。
对于成员函数,函数声明必须与其定义一致。
如果函数被声明为const 成员函数,那么函数定义时形参表后面也必须有const。
理解第一行代码,这行代码说明现在正在定义类Sale_item 的函数avg_price() 。而且这是一个const 成员函数,这个函数没有(显示的)形参(但有隐式的this 指针形参),返回double类型的值。
三、编写Sale_item类的构造函数
在定义类时,没有初始化它的数据成员的,都是通过构造函数来初始化其数据成员的。
1、构造函数是特殊的成员函数——和类同名,没有返回类型
构造函数是特殊的成员函数,与其他成员函数不同,构造函数和类同名,而且没有返回类型。而与其他成员函数相同的是,构造函数也有形参表(可能为空)和函数体。
一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参。
构造函数的形参指定了创建类类型对象时使用的初始化式。通常,这些初始化式会用于初始化新创建对象的数据成员。
构造函数应该确保每个数据成员都完成了初始化。
默认构造函数:没有形参的函数,表示当定义了一个对象却没有为它提供(显示的)初始化式时应该怎么办。
vector<int> vi;//vector默认构造函数生成一个没有元素的vector向量对象
string s; //string 的默认构造函数会产生空的字符串,相当于“ ”
Sale_item item;//默认初始化item对象,isbn初始化为空的字符串,units_sold和revenue初始化为0.
2、构造函数的定义
和其他成员函数一样,构造函数必须在类中声明,但可以再类中或类外定义。
构造函数必须放在类的public 部分
class Sale_item{
public:
double avg_price() const;//函数声明,形参表为空,返回double类型的值,const说明这是一个const成员函数
bool same_isbn(const Sale_item &rhs) const
//返回bool类型值,有一个const Sale_item类型的引用
{return isbn==rhs.isbn;}
Sale_item(): units_sold(0),revenue(0){}//显示定义一个构造函数
private:
std::string isbn;
unsigned units_sold;
double revenue;
};
Sale_item(): units_sold(0),revenue(0){}//构造函数,函数体和形参为空,形参为空表明正在定义的是默认调用的构造函数,不需要提供任何初值。
3、构造函数的初始化列表
Sale_item(): units_sold(0),revenue(0){}//构造函数,函数体和形参为空,形参为空表明正在定义的是默认调用的构造函数,不需要提供任何初值。
在冒号和花括号之间的代码称为 构造函数的初始化列表。
构造函数的初始化列表为类的一个或多个数据成员指定初值。它跟在构造函数的形参表之后,以冒号开头。
构造函数的初始化式是一系列成员名,每个成员后面是括在圆括号中的初始值,多个成员的初始化用逗号分隔。
4、合成的默认构造函数
如果没有为一个类显示定义任何构造函数,编译器会自动为这个类生成默认构造函数。
编译器创建的默认构造函数通常称为 合成的默认构造函数,它会依据如同变量初始化的规则初始化类中所有成员。
对于具有类类型的成员,如string类型的isbn ,则会调用该成员所属类自身的默认构造函数实现初始化,初始化为空串;
内置类型成员的初值依赖于对象如何定义,如果对象在全局作用域中定义(即不在任何函数中)或定义为静态局部对象,则这些成员将被初始化为0。
如果对象在局部作用域中定义,则这些成员没有初始化。
除了给它们赋值之外,出于其他任何目的的对未初始化成员的使用都没有定义。