类与数据抽象
类
-
类即抽象数据类型
-
成员函数只能重载本类的其他成员函数,这个主要是因为重载需要在同一个作用域下
-
const成员函数,定义和声明处均需要制定为const,表明该函数不会改变类的对象的成员,相比而言inline关键字更为随意,随便在哪边指定都可以,并可以同时指定
-
特别说明,基于const的重载,基于成员函数是否为const,可以重载一个成员函数,本质上成员函数携带一个this指针,这个const实质是修饰this指针,即形参如果是指针或者应用,其是否是const将导致重载
-
类的成员访问可以采用.或者->,但定义的类型成员采用作用域操作符访问::
-
成员函数的返回类型是不在类的作用域中的,需要特别注意
-
构造函数不能声明为const,毕竟构造函数需要初始化其成员变量要声明为const,则无法改变其成员
-
对于const或者引用类型的成员变量,在构造函数中必须使用成员初始化列表形式进行初始化,成员初始化的顺序是按照其声明的顺序进行的,不是按照初始化列表中的顺序执行
-
合成的默认构造函数使用变量的初始化规则初始化成员,即类类型调用其构造函数,全局的对象才初始化,局部作用域内的内置或者复合数据类型不进行初始化。
-
常见误用
MyClass myObj();这个是声明一个函数不是定义一个类,应该使用
MyClass myObj;或者
MyClass myObj = MyClass(); -
explicit阻止其进行隐式类型转换
-
友元允许一个类将对其非公有成员的访问权授予指定的函数和类。一般来讲,必须先定义包含成员函数的类,才能将成员函数设为友元,另一方面,不必预先声明类和非成员函数来将它们设为友元
-
友元的声明不受累的访问权限影响,可以声明在类的任何位置
-
static成员函数没有this指针,同时不能访问非static的成员变量,同时static成员函数不能是const,同时不能为虚函数
-
static数据成员必须在类定义体外部定义,不像普通数据成员,其不是在构造函数中进行初始化,需在定义时进行初始化。如果是const static数据成员可以在声明的时候进行初始化
复制控制
-
默认构造函数、复制构造函数、赋值操作符、析构函数
-
合成的复制构造函数行为,执行逐个成员(非static成员)初始化,数组成员其每一个对象也会进行复制
-
禁止复制,显示的声明其复制构造函数为private
-
合成的赋值操作符行为,逐个成员赋值,和合成的复制构造函数行为一致,因此需要定义复制构造的时候往往也需要定义赋值操作符
-
合成的析构函数按照对象创建的逆序撤销每一个非static成员,即使我们自己定义了一个析构函数,合成的析构函数仍然会被执行,执行顺序:先执行自定义的析构,再执行合成的析构
-
智能指针(引用计数)
重载操作符和转换
- 不能重载的操作符
:: .* . ?:
-
重载操作符不能重新定义内置类型对象的操作符含义
-
操作符的优先级、结合性、操作数数目不能改变
-
一般将算术和关系操作符定义为非成员函数(若要访问类的私有部分通常将其定义为类的友元),赋值操作符定义为成员函数
-
逗号,取地址,逻辑与,或通常不进行重载,这样符号有内置的意义,如果重载将失去这些功能
-
IO重载时,通常需要包括一个流对象参数,并且通常是非const的引用,首先流对象需要被改变,故非const,其次流对象不能复制,故是引用
ostream & operator<<(ostream &out,const myClass &);
istream &operator>>(istream &in, myClass &);第二个参数为非const,因为数据必须写入 -
IO操作符必须为非成员函数,因为左操作数必须为流对象,如果是成员的话,则左操作数为类对象this
-
定义了调用操作符的类,其对象称为函数对象
-
转换操作符定义,注意与调用操作符的区别,二者均为类的成员函数
转换操作符 operator type(),虽然未定义返回类型,但需要返回一个type类型
调用操作符 type operator() (参数列表)