[c++primer][12]类
12.1 类的定义和声明
概述
类是将数据与操作封装的抽象数据类型。
访问标号:public,可被使用该类型的所有代码访问;private,可被类成员访问;protected:,受保护成员
成员函数
1、在类内部,声明成员函数是必须的,定义成员函数是可选的;类外部定义的函数必须指明在类的作用域中。
2、成员函数有一个隐含实参(对象指针),将函数绑定到调用函数的对象;
3、const成员函数不能改变其所操作的对象的数据成员,const必须同时出现在声明和定义处。
4、inline函数:类内部定义的函数默认为inline;在声明或定义处指定inline都是合法的
类声明和类定义
只声明而不定义类称为前向声明,是不完全类型。只能用于定义指向该类型的指针及引用,或用于声明使用该类型作为形参类型或返回类型的函数。
在创建类的对象之前,在使用引用或指针访问类的成员之前,必须已经定义类。
定义类的对象
Sales_item item1; //C++引入 class Sales_item item1; //从C继承而来
12.2 隐含的this指针
何时使用this指针
当我们需要将一个对象作为整体引用而不是引用对象的一个成员时。最常见的情况是当该函数返回对调用该函数的对象的引用。
从const成员函数返回*this
在普通的成员函数中,this的类型是一个指向类类型的const指针。
在const成员函数中,this的类型是一个指向const类类型对象的const指针。
const成员函数只能使用const成员(数据和函数);非const对象可以使用任一成员,但非const版本是一个更好的匹配。
mutable数据成员
const成员函数可以改变mutable成员。要将数据成员声明为可变的,必须将关键字mutable放在成员声明之前
12.3 类作用域
定义类型的成员,使用作用域操作符类访问;
typedef std::string::size_type index;//(在类Screen中)
如Screen::index
形参表和函数体处于类作用域中,函数返回类型不一定在类作用域中。
类的成员被屏蔽时,可以通过用类名限定成员名或显式使用this指针来使用它。
12.4 构造函数
构造函数不能声明为const。
构造函数初始化式
构造函数可以定义在类的内部和外部;但初始化式只在构造函数的定义中而不是声明中指定。
构造函数分两阶段执行
1)初始化阶段;2)普通的计算阶段(函数体)
不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化;在初始化列表中没有提及的每个成员,使用与初始化变量相同的规则来进行初始化。
默认构造函数初始化规则
类类型成员运行各自的默认构造函数;内置或复合类型成员初始值依赖于对象作用域(局部作用域不被初始化,全局作用域被初始化为0)
没有默认构造函数的类类型成员以及const或引用类型的成员,必须在构造函数初始化列表中进行初始化;成员被初始化的次序就是定义成员的次序。
默认构造函数
未提供初始化式或为所有形参提供默认实参的构造函数称为默认构造函数;只有当类未定义构造函数时,编译器才会自动生成一个合成的默认构造函数,使用变量初始化规则初始化成员。
只要定义了一个构造函数,编译器不会再生成默认构造函数,应该显式提供一个默认构造函数,并且必须显式初始化成员。
C++在new时的初始化的规律:
对于有默认构造函数的类,不论有没有括号,都用默认构造函数进行初始化;如果没有默认构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0。
隐式类型转换
可用单个实参调用的构造函数定义了从形参类型到该类类型的一个隐式转换。
在类定义体内用explicit声明抑制构造函数定义的隐式转换;当转换确实有用,可以显示构造对象。
12.5 友元
友元机制允许类将其非公有成员的访问权授予指定类或函数。
必须先定义包含成员函数的类,才能将成员函数设为友元;另外,不必预先声明类和非成员函数来将他们设为友元。用友元引入的类名和函数(声明或定义),可以像预先声明的一样使用。
12.6 static类成员
可以通过作用域操作符直接调用static成员,或通过对象、引用或指向该类类型对象的指针间接调用。
static成员函数
static成员函数不能声明为const,也不能声明为虚函数;static关键字只出现在类定义体内部声明处;
static成员函数没有this形参,它可以直接访问所属类的static成员,但不能直接使用非static成员。
static数据成员
static数据成员可以声明为任意类型,static关键字只在定义体内;static成员不通过类构造函数进行初始化,而是在定义时进行初始化。
static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象关联。
特殊的整型const static成员
只要初始化式是一个常量表达式,整形const static数据成员就可以在类的定义体中进行初始化。但是该数据成员仍必须在类的定义体之外进行定义。
在类内部提供初始化式时,成员的定义不必再指定初始值。
// definition of static member with no initializer; // the initial value is specified inside the class definition const int Account::period;
static成员不是类对象的组成部分
1、static数据成员可以是该成员所属的类类型
2、static数据成员可用作默认实参