补充:基础议题
仔细区别指针(pointer)和引用(references)
指针可以为null,但是不存在null引用,引用必须总代表某个对象。使用空指针建立引用,是未定义行为,编译期会产生任何可能的输出。
二者的另一个重要差异就是,指针可以重新赋值,引用却总是指向它最初获得的那个对象。
总结:当你知道需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由pointers完成(例如operator[]
),你就应该选择references。其他任何时候,都使用pointers。
最好使用C++的类型转换操作符
旧式的C转型方式第一个问题是语义不明确,它几乎允许你将任何类型转换为任何类型,这是非常拙劣的。如果每次转型都能够更精确地指明意图则更好。第二个问题是辨识度低(CRE:我个人不认为它辨识度低)。
static_cast
基本上拥有与C旧式转型相同的威力和意义,以及相同的限制。其他新式C++转型操作符适用于更集中、范围更狭窄的目的。
绝对不要以多态方式处理数组
CRE:由于基类对象和派生类对象的size很可能不是相等的。如果把派生类数组当作基类数组,数组按整数索引取元素时会发生指针的算术运算,指针算术运算又是基于size的,编译期就会被误导,继而发生未定义行为(UB)。
非必要不提供默认构造函数
- 避免创建未初始化的对象。(如果类提供了默认构造函数,用户可以创建一个未初始化的对象)
- 提高类的设计清晰度。(明确指出这个类的对象需要特定的初始化参数,而不是凭空产生)
- 允许使用const和引用成员。(它们必须在对象构造时初始化。默认构造函数无法提供初始化列表)
- 减少性能开销。(添加无意义的默认构造函数也会影响类的效率)
//补充:“最令人讨厌的解析”
//(在C++中,如果一个声明的语法可以被解释为一个函数声明,编译器将优先将其解释为函数声明。这是为了与C风格的函数声明保持一致。)
MyClass obj1();//obj1被编译器认为是函数
MyClass obj2(....);//obj2被编译器认为是对象
(END)