Tip01C++为一个语言联邦

CC++是以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的递增次数取决于和谁比较。

++ab++a=6a>b,返回(++a)a = 7;

++ab+10++a=6,a<b+10,返回(b), a = 6


Tip03:尽可能使用const

一、成员函数是const的含义,Class::Function() const

1.bitwise constness:成员函数不能改变任何成员变量,也就是说不能更改对象的任何一个bit

但是如果,成员变量是指向对象的指针,按照bitwise的观点,成员函数不能改变该指针,相当于在该成员函数内,指针是指针常量。然而,在const成员函数内,却可以改变指针指向的对象。

但是,const成员函数的初衷,就是防止改变指针指向的对象。

PS:编译器就是bitwise constness

2.logical constnessconst成员函数可以修改成员变量,但只有编译器通过的情况下。

既然成员函数是const,对于编译器而言,它就绝不能修改成员函数,如何让它能通过编译器检查呢?在成员变量添加修饰符mutable,可以释放掉成员变量的bitwise constness约束。也就是说,即使在const成员函数内,也可以修改mutable成员变量。


二、non-const版本调用const版本。

通常const版本的non-const的函数实现是一样的,唯一的不同是返回类型。这时,我们可以在non-const版本调用const版本。

(*this)转换为const类型static_cast<const T>(*this)。这样就才能调用const版本的函数

static_cast<const T&>(*this).function()

const版本的返回值(const T&)转换成non-const

const_cast<T &>( static_cast<const T&>(*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一定指向了一个历经初始化的对象