条款01:把C++当作一个语言联邦
c++不是简单的“添加了面向对象特性的c语言”。我们可以认为c++是由以下四个次语言组成的语言。
1,C语言: 说到底,c艹仍然是已c为基础的,区块,语句,预处理器,内置数据类型,统统来源于c语言。
2,面向对象c++:这一部分包含了 封装,继承,多态,等等面向对象编程语言最直观的特征。
3,Template c++:泛型编程。
4,STL:是一个template程序库。包含有容器,迭代器,算法,以及程序对象。
每个语言都有自己的规约。记住这4个语言你会发现c艹容易理解得多。
条款02:尽量以 const,enum,inline 替换 #define
编译过程:.c文件--预处理-->.i文件--编译-->.o文件--链接-->bin文件
预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。可见预处理过程先于编译器对源代码进行处理。预处理指令是以#号开头的代码行。
当我们写出如下代码:
#define ASPECT_RATIO 1.653
可能记号ASPECT_RATIO并没有被编译器看见;也许在预处理阶段她就被预处理器移走了。当由于这个记号发生了error的时候,编译器的提示可能是1.653,而不是ASPECT_RATIO。这会让人摸不到头脑、
解决之道是使用常量来替换上面的宏定义
const double ASPECT_RATIO = 1.653;
作为一个语言常量ASPECT_RATIO肯定会被编译器看到。因为预处理器是将目标进行盲目的替换,可能导致目标代码出现多份1.653,若改用常量定义则不会出现这样的情况。
使用常量有两点需要注意:
1,定义常量指针。由于常量指针经常放在头文件内,所以有必要将指针声明为const。
const char *authorName = “Shenzi”;
在c++中定义字符串最好使用string
cosnt std::string authorName("Shenzi");
2,class专属常量。为了限定这个常量的作用域在class内,必须要让她成为一个class成员。为了确认常量只有一份实体,所以必须将其设定为static成员。
#include<iostream> using namespace std; class GP{ public:static const int NTm = 5; //声明 int soc[NTm]; }; const int GP::NTm; //定义 如果没有这句,接下来取地址会出错 int main(){ int const *pi = &GP::NTm; return 0; }
当然,由于部分编译器不支持类内的声明式上获得初值,可以将初值放在定义式。
#include<iostream> using namespace std; class GP{ public: static const int NTm; // int soc[NTm]; //此时无法在类内使用NTm //为了在类内使用NTm可以用 enum{NTm = 5}; 替换静态变量 }; const int GP::NTm = 5; int main(){ int const *pi = &GP::NTm; return 0; }
另一种常见的#define误用情况是,其实现的宏看起来很像函数,但是并没有导致函数调用。
比如下面的代码
#define fun(a,b) a*b;
我们进行如下运算
2.0/fun(1.0,2.0);
我们期望的算法是 2.0 / (1.0 * 2.0)
但是编译器会把代码解释为 2.0 / 1.0 * 2.0
针对这种问题的解决方案是定义inline的模版函数
template<class T> inline T fun(const T& a,const T& b){ return a*b; }