Tip01:C++为一个语言联邦
C:C++是以C为基础,这一部分就是基础的C,没有模板(template),没有异常(exceptions),没有重载(overloading)
Object-Oritented C++:即C with Class,面向对象部分。
Template C++:C++的泛型编程
STL:一个template程序库。
编程守则:
1.对于C而言,因为C中没有Object的概念,因此值传递(pass-by-value)比引用传递(pass-by-reference)高效。
2.对于Object-Oritented C++和Template C++,由于有了构造函数和析构函数的存在,pass-by-reference-to-const更好
3.对于STL,因为迭代器和函数对象都是在C指针上构建的,所以旧式的C pass-by-value再次适用
Tips02:尽量以const,enum,inline代替#define
一、原因一:#define使用的名称可能未进入记号表(symbol table),导致调试困难。
二、enum hack的用法。
在某些旧式编译器上,可能不允许static成员在其声明式上获得初值。当然,可以将初值放在定义式上。
然而,class编译期间需要一个class常量。如
class GamePlayer{ private: static const int NumTurns = 5; int scores[NumTurns]; }
如果编译器不通过static const int NumTurns = 5;就需要用到enum hack。
class GamePlayer{ private: enum {NumTurns = 5}; int scores[NumTurns]; }
补充一点,初始化static成员变量。在头文件,类定义中声明static变量
static T sMember
然后在源文件(.cpp)定义该static变量
T Class::sMember = value
三、#define定义的函数宏,最好用inline+tepmlate替代
#define CALL_WITH_MAX f((a) > (b) > (a) : (b)) int a = 5 , b = 0; CALL_WITH_MAX(++a, b) a = 7; CALL_WITH_MAX(++a, b+10) a = 6;
a的递增次数取决于和谁比较。
①++a,b。++a=6,a>b,返回(++a),a = 7;
② ++a,b+10。++a=6,a,返回(b), a = 6
Tip03:尽可能使用const
一、成员函数是const的含义,Class::Function() const。
1.bitwise constness:成员函数不能改变任何成员变量,也就是说不能更改对象的任何一个bit。
但是如果,成员变量是指向对象的指针,按照bitwise的观点,成员函数不能改变该指针,相当于在该成员函数内,指针是指针常量。然而,在const成员函数内,却可以改变指针指向的对象。
但是,const成员函数的初衷,就是防止改变指针指向的对象。
PS:编译器就是bitwise constness
2.logical constness:const成员函数可以修改成员变量,但只有编译器通过的情况下。
既然成员函数是const,对于编译器而言,它就绝不能修改成员函数,如何让它能通过编译器检查呢?在成员变量添加修饰符mutable,可以释放掉成员变量的bitwise constness约束。也就是说,即使在const成员函数内,也可以修改mutable成员变量。
二、non-const版本调用const版本。
通常const版本的non-const的函数实现是一样的,唯一的不同是返回类型。这时,我们可以在non-const版本调用const版本。
①将(*this)转换为const类型static_cast
static_cast(*this).function()
②将const版本的返回值(const T&)转换成non-const。
const_cast( static_cast (*this).function())//(*this)返回的是reference of T
三、为什么non-const版本不能调用const版本
const成员函数绝对不会改变对象的逻辑状态(logical state),但non-const成员函数却没这条限制。如果const版本调用non-const版本,就会发生const函数内改变了对象的逻辑状态,不管实际上有没有改变,这完全取决于non-const版本
Tip04:确定对象被使用前初始化
一、赋值(assignment)和初始化(initialization)的区别
XXX::XXX(){ Member1 = xxx; Member2 = xxx; }
这叫赋值。而Java中不存在初始化列表,因此只能采用这种初始化方式,所以在Java的初始化对应的是C++的赋值
二、初始化的顺序
类的成员变量总是以其声明的方式被初始化。即类中声明的顺序是A,B,C,D…,那即使初始化列表的顺序是B(xxx),D(xxx),C(xxx),A(xxx),实际初始化顺序依然是A,B,C,D
三、什么是non-local static对象。
一般声明在函数内部的变量,称之为局部变量或者本地(local)变量。所以,non-local static对象,就是在函数体之外声明的static对象
四、non-local static对象的初始化顺序。
对于把不同的编译单元内的non-local static对象的初始化顺序根本,没有明确定义。
五、如果其他类用到了non-local static对象,但不能确定该对象是否初始化,怎么解决。
用local static对象替换non-local static对象。C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇到该对象之定义式”时被初始化。用函数调用(返回一个reference指向local static对象)替换non-local static对象,那么该reference一定指向了一个历经初始化的对象