71. 操作符重载:
(1)不能通过连接其他符号来创建任何新操作符,如**(幂)非法
(2)不内置类型定义额外的新操作符(如不能为数组定义+)
(3)重载操作符必须具有至少一个类类型或枚举类型的操作数
(4)优先级和结合性是固定的,重载操作符使用默认实参非法
(5)操作符定义为非成员函数时,通常必须将它设置为所操作类的友元
(6)赋值操作符,取地址操作符,逗号操作符对类类型操作数有默认含义
(7)关联容器键类型应定义<操作符,顺序容器中,为了算法可用,应定义==,<操作符
(8)选择成员or 非成员实现:=,[ ], (), ->必须定义为成员复合赋值也应定义为成员,++, -- , *等一般为类成员,对称的操作符,如算术,相等,关系,位操作符,最好定义为非成员函数。
72.函数对象,定义了operator()成员函数
可用参考标准库函数对象(类模板),在C++ Prime 第452页
73. 类类型可转换为其他类型,需要定义operator 类名() const
类类型转换之后不能再跟另一个类类型转换。标准转换可放在类类型转换之前。
74. 多态
(1) 动态多态: 类继承和虚函数机制(动态绑定实现)
(2) 静态多态: 1. 非参数化多态(函数重载,运算符重载) 2. 参数化多态:泛型编程(类型作为参数)
75. 动态绑定:通过基类的引用(或指针)调用虚函数,发生动态绑定。引用(或指针)可指向基类也可指向派生类对象,用引用(或指针)调用的虚函数在运行时确定。
76. 一般基类需要定义虚析构函数,static成员函数不可为虚函数,virtual只在类内部的成员函数声明中出现,不能在类定义体外函数定义上出现。
77. 基类中的public成员可被派生类访问,但private成员不能被访问,protected成员可被派生类访问,但不能被其他用户访问。
基类只对外部提供public,而派生类则可以访问基类的protected, 但在派生类定义函数内部不能访问基类对象的protected。
78. 引用和指针的静态类型与动态类型可以不同,这是C++用以支持多态性的基石。
对象的类型已知且不变,对象是非多态的。对象的动态类型总是与静态类型相同,这与引用和指针相反。
79. (1) 编译时确定非virtual调用
(2) 覆盖虚函数机制
80. 通过基类的引用或指针调用虚函数时,默认实参为在基类虚函数中声明的值,若通过派生类的指针或引用调用虚函数,则默认实参是在派生类的版本中声明的值。
81. 公用,私有和受保护的继承
(1) 公用继承(public基类):基public -> 派public; 基protected -> 派protected
(2) 受保护继承(protected基类):基public, protected -> 派protected
(3) 私有继承(private基类):基所有 -> 派private
82. 默认继承保护级别
class Base;
struct D1: Base -> struct D1: public Base
class D2: Base -> class D2: private Base
83. 友元关系与继承:友元关系并不能继承。基类的友元对派生类成员没有特殊访问权限。
84. 派生类-> 基类:
(1) 引用转换不同于转换对象
(2) 用派生类对象对基类对象进行初始化或赋值
(3) 派生类到基类转换的可访问性
85. 派生类构造函数:先调用基类的默认构造函数,然后再执行派生类的构造函数。
(1) 向基类构造函数传递实参:
Bulk_item(const std::string &book, ...): Item_base(book, sales_price), min_qty(), discard() {}
(2) 派生类只能使用直接基类构造函数初始化,初始化直接基类
86. 复制构造函数,赋值构造函数,析构函数一般都是先基类,再派生类的顺序进行。
(1) 对于复制构造函数,若不定义,则使用合成复制构造函数(先基类复制,再派生类部分),若派生类定义了自己的复制构造函数,该复制构造函数一般应显式使用基类复制初始化自己基类部分,不然,则运行Base默认构造函数初始化对象(会出问题的)
(2) 赋值同复制,若派生类显式定义了自己的赋值操作符,则必须对基类部分进行显式赋值。Base::operator=(rhs);
(3) 析构函数不一样,只负责撤销自己的部分,从底往上逆序撤销基类。
87. 基类的虚析构函数总是需要的,防止指针指向派生类。复制构造函数,构造函数,赋值操作符一定不能用虚函数。
88. 派生类作用域中嵌套着基类作用域,若派生类中成员名与基类相同,则屏蔽基类中成员,若在派生类中还想用基类成员,则Base::mem; 在派生类中定义与基类函数名一样的函数,则屏蔽基类中的,是屏蔽,不是重载,不管形参等怎样不同都屏蔽。
局部作用域中声明的函数不会重载全局作用域中函数。
基类作用域 {
派生类作用域
}
89. 派生类中的重载函数,要么重定义函数,屏蔽基类,要么不定义,用基类重载函数。若想打破,则用using Base::函数名; 不用形参表。接着定义自己的函数。
90. 派生类中定义了与基类虚函数同名函数,但形参不一样,则屏蔽,若又定义了相同形参函数,则依次管用。
91. 纯虚函数,声明如下:virtual 返回类型 函数名(参数) = 0;
纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,不能实例化,但可以定义该类类型的指针或引用,同时,该类的派生类中必须实现虚函数具体行为,不然报错。
92. 如果虚函数的基类实例返回类类型的引用或指针,则该虚函数的派生类实例可以返回基类实例返回的类型的派生类(或者类类型的指针或引用)。
93. 句柄类,管理类类型指针,特别对于基类和派生类问题有效。句柄类(智能指针)是存储指向动态分配(堆)对象指针的类。
最后加了几个注意点,写完感觉C++的语法真的很复杂,比java复杂好多。个人感觉java取消了操作符重载是明智的,而且取消了多继承,改用接口来规范更是一大进步。下面一段时间希望来将java的多个注意点整理好搬上来,在java篇的注意点中整好与c++的语法特性相比,让大家感受一下java的编程优势。(我并不是一个java控,本人最喜欢的语言是python)。