《Effective C艹》读书笔记(1)

条款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;
}

 

猜你喜欢

转载自bbezxcy.iteye.com/blog/2240386