第一部分:习惯C++(条款1-4)

来源:互联网 发布:3d地球仪软件 编辑:程序博客网 时间:2024/05/17 07:03

这里是effective C++第一部分

条款1C++的整体认识。它包括 1. C部分。C++C语言为基础发展而来。2.面向对象部分。3.C++泛型编程部分也叫template C++. 4.STL

条款2const,enum,inlinedefine替换

              1.#define RATIO 3.14  改为const double Ratio = 3.14这么做是有原因的,#define作为预处理器也许不被视作语言的一部分。记号RATIO也许没有被编译器看见;也许      编译器开始处理源码时就被预处理器移走了。于是记号RATIO可能没有进入记号表。于是当你运用此常量可能获得一个编译错误。但是作为一个语言常量Ratio当然就会进入     记号表。另外使用常量可能获得比预处理更少的代码,因为预处理器只是盲目的替换。

               2.当你在你的class内需要在编译期间一个常量的时候这种情况会有所不同。enum可以作为补偿。看下面的列子

               class Game

               {

                       private

                              enum{NumTurns=5};

                       int  scores[NumTurns];

                      ....

                }

              enum对于有时候更像define,取const的地址是合法的,但是取enum的地址是不合法的。如果你不想让别人获得一个pointer或者reference指向你的某个整数常量enum          可以帮你约束。

            3.inline 

              看个列子  #define CALL_MAX(a,b)f((a)>(b)?(a):(b))来看不可思议的调用:

             inta = 5, b=0;

            CALL_MAX(++a,b);  //a被累加2

             CALL_MAX(++a,b+10) //a被累加1

            改成inline函数可以避免类似的事情发生

          template<typename T>

            inlinevoid Call_Max(const T& a,const T& b)

           {

              f(a>b?a:b);

            }

条款3const

     const是多才多艺的

    首先注意区别 const int* a *const int b a是指向一个int常量的指针,意味着a也可以指向其他int常量。b是一个const指针,只能够指向一个固定的内存,当然对它所指向的值是否可以修改不是由它说了算。

    函数返回值为const避免不必要的修改

   const成员函数标示哪些成员函数可以修改成员变量,哪些不可以  函数参数为const引用可以提高效率。注意基于const的成员函数的重载

  class Text

  {

    public:

     ...........

     const char& operator[ ](intx) const

       { return text[x];}

     char& operator[int x]

      { return text[x];}

     private:

     std::string text;

  };

 Text tb("Hello");

 std::cout<<tb[0]; //调用non-const

 tb[0] = 'x'; //没问题

Text ctb("World");

 std::cout<<ctb[0]; //调用const

ctb[0] = 'x'; //错误

应该如何避免constnon-const代码的重复?non-const调用const

class Text

  {

    public:

     ...........

     const char& operator[ ](intx) const

       { return text[x];}

     char& operator[int x]

      { return 

        const_cast<char&>(

             static_const<const Text&>(*this)

              [x]);

       }

     private:

     std::string text;

  };

上面的代码第一个const_cast是移除const特性。第二个static_cast是加上const特性。那么这句话的意思就是加上const特性在Text上面,然后对其求下标运算即调用了const成员函数版本,这里如果不加上const,那么函数会自己调用自己导致一个死循环。因为其返回值是一个const,我们希望非const Text的成员变量值是可以改变的,所以我们移除它的const特性了。

   那么用const调用non-const可以吗?答案是不可以的,因为const承诺不改变,而non-const没有这个说法,这里就存在成员有可能被non-const改变的危险,这是一种错误的行为

 

条款4 对象使用前被初始化

 这个条款有一个值得注意的地方。例子里面有很多说明了

class FileSystem

{

 public:

  int num() const;

 ........

};

extern FileSystem tfs;

另外一个客户:

class Dir

 {

    public:

      Dir(....);

     ........

 };

  Dir::Dir()

  {

    ......

    int disks = tfs.num();

  }

//假设客户创建对象

Dir temp(....);

这里除非tfstemp之前初始化,否则就会有错误

下面是一个解决办法:

class FileSystem{ .... };

FileSystem& tfs()

{

  static FileSystem fs;

  return fs;

}

class Dir{...};

Dir::Dir(...)

{

    int disks = tfs().num();

   .....

}

Dir& temp()

{

 static Dir dir;

 retuen dir;

}

以上就是典型的单例模式