Effective C++ 学习历程001

Effective C++ 学习历程001

      自从大一下接触C++面向对象程序设计,我就对一直在学习C++ 这门语言,当然了也一直很喜欢C++。在之前刚刚开始C语言程序设计时,自己还不喜欢编程这门学问。后来,慢慢喜欢上编程,正是跟随着C++ 语言的慢慢学习与积累的。嗯,我很喜欢C++这门语言!
      那就从一本挚爱的图书《Effective C++ 》开始吧,也当是给“Effective C++ 学习历程”做个简单的开始。
  1  namespace  testItem01
  2  {
  3  } // namespace testItem01
  4  //  ====================================================================
  5  //  --- 条款02:尽量以const,enum,inline替换 #define
  6  //  注意:
  7  //  1    对于单纯变量,最好以const 对象或是 enumS 替换 #defineS 。。。
  8  //  2    对于形似函数的 宏(mactos),最好改用inline(结合 template) 函数替换 #defineS 
  9  //  3
 10  namespace  testItem02
 11  {
 12      template  < typename T >
 13      inline T   MAX_TEMP( const  T &  a , const  T &  b)
 14      {  return  (a > ?  a : b) ; }
 15       void  exampleFunc()
 16      {
 17          cout  <<   "  define constant ,using #define ,enum , const Type  \n "  ;
 18           #define  DEFINE_NUM  10
 19           enum  { ENUM_NUM  =   10   } ;  //  ..
 20           const   int  CONST_NUM  =   10  ;
 21          cout  <<   "  DEFINE_NUM  ENUM_NUM  CONST_NUM : "
 22                <<  DEFINE_NUM  <<  setw( 5 <<  ENUM_NUM  <<  setw( 5 <<  CONST_NUM  <<   " \n "  ;
 23           /*
 24          char    str1[DEFINE_NUM] ; // okokok 
 25          char    str2[ENUM_NUM] ;// okokok 
 26          char    str3[CONST_NUM] ;// okokok 
 27           */
 28           //  #define 导致的错误  ..
 29          cout  <<   "  Error , use #define  \n "  ;
 30           #define  MAX_DEFINE(a,b) ((a) > (b) ? (a) : (b))
 31           int  a  =   5 , b  =   0 ;
 32          cout  <<   "  a = 5, b = 0; MAX_DEFINE(++a, b):  "  ;
 33          cout  <<  MAX_DEFINE( ++ a, b)  <<   " \n "  ; //  a 的值增加了2次
 34          cout  <<   "  a:  "   <<  a  <<   "  ,MAX_DEFINE(++a, b+10) :  "  ;
 35          cout  <<  MAX_DEFINE( ++ a, b + 10 <<   " \n "  ;  //  a 的值只增加了1次
 36          cout  <<   "  a:  "   <<  a  <<   " \n "  ;
 37          cout  <<   "  OKOKOK , use inline template  \n "  ;
 38          a  =   5 , b  =   0 ;
 39          cout  <<   "  a = 5, b = 0; MAX_TEMP(++a, b):  "  ;
 40          cout  <<  MAX_TEMP( ++ a, b)  <<   " \n "  ; //  a 的值增加了2次
 41          cout  <<   "  a:  "   <<  a  <<   "  MAX_TEMP(++a, b+10) :  "  ;
 42          cout  <<  MAX_TEMP( ++ a, b + 10 <<   " \n "  ;  //  a 的值只增加了1次
 43          cout  <<   "  a:  "   <<  a  <<   " \n "  ;
 44      }
 45  } // namespace testItem02
 46  //  ====================================================================
 47  //  --- 条款03:尽量使用 const 
 48  //  注意:
 49  //  1    将某些东西声明为 const可以帮助编译器侦测出错误语法。const可被施加于任何作用域内的
 50  //       对象、函数参数、函数返回类型、成员函数本体 
 51  //  2    编译器强制执行(实施)bitwise constness 。但你编写程序时应该使用“概念上的常量性”(conceptual constness)
 52  //  3    当 const 和 non-const成员函数有着实质等价的实现时,令non-const版本去调用const版本可避免代码重复 。
 53  namespace  testItem03
 54  {
 55       void  func1( const   char *  pChar) { cout  <<   "  void func1(const int* pInt):  "   <<  pChar  <<   " \n "  ; }  //
 56       void  func2( char   const   *  pChar)
 57      { cout  <<   "  void func2(int const * pInt):  "   <<  pChar  <<   " \n "  ;}  //  the same as func1 
 58       //  -------------------------
 59       class  TextBlock
 60      {
 61       private :
 62          std:: string  text_ ;
 63       public :
 64          TextBlock() {}
 65           // TextBlock(const char* str) : text_(str) {}  //
 66          TextBlock( const  std:: string &  str) : text_(str) {}  //
 67           //  
 68           const   char &   operator  [](std::size_t pos)  const
 69          {
 70              cout  <<   "  const char& operator [](std::size_t pos) const \n "  ;
 71               return  text_[pos] ;
 72          }
 73           /*  1 ==========
 74          char& operator [](std::size_t pos)
 75          {
 76              cout << " char& operator [](std::size_t pos) //1==\n " ;
 77              return text_[pos] ;
 78          }  */   // 2 ========== non-const 跳转 const 版本 + 过程转换 
 79           char &   operator  [](std::size_t pos)
 80          {
 81              cout  <<   "  char& operator [](std::size_t pos) //2==\n "  ;
 82               return  const_cast < char &> (static_cast < const  TextBlock > ( * this )[pos] ) ;
 83          }
 84           //  
 85      } ;
 86       void  print_0( const  TextBlock &  ctb)
 87      { cout  <<   "  ctb[0]:  "   <<  ctb[ 0 <<   " \n "  ; } // 调用const char& operator [](std::size_t pos) const
 88       //  ------------关键字 mutable mutable mutable ---------
 89       class  CTextBlock
 90      {
 91       private :
 92           char *  pText ;
 93          mutable size_t textLength ; // 可以在 const成员函数改变该成员变量 
 94          mutable  bool    lengthIsValid ; // 可以在 const成员函数改变该成员变量 
 95       public :
 96          size_t length()  const  ;
 97           //  
 98      } ;
 99      size_t CTextBlock::length()  const // 可以在 const成员函数改变该成员变量 textLength ,lengthIsValid
100      {
101           if ( ! lengthIsValid)
102          {
103              textLength  =  std::strlen(pText) ;
104              lengthIsValid  =   true  ;
105          }
106           return  textLength ;
107      }
108       //  
109       void  exampleFunc()
110      {
111           char  greeting[]  =   " Hello "  ;
112           char *  p  =  greeting ;  //  non-const pointer ,non-const data
113           const   char *  cp  =  greeting ; //  non-const pointer ,const data
114           char *   const  pc  =  greeting ; //  const pointer ,non-data
115           const   char *   const  cpc  =  greeting ; //  const pointer ,const data
116          func1(p) ; func1(cp) ; func1(pc) ; func1(cpc) ;
117          func2(p) ; func2(cp) ; func2(pc) ; func2(cpc) ;
118           //  -------------------------------------------
119          std::vector < int >  iVec( 5  , 1 ) ;
120           //  
121          cout  <<   "  *iVec.begin():  "   <<   * iVec.begin()  <<   " \n "  ;
122           const  vector < int > ::iterator it  =  iVec.begin() ; //  const vector<T>::iterator == T* const
123           * it  =   10  ;  //  没有问题,实际改变it所指物,但违背正常逻辑 
124           // ++it ;  // 错误!it 是 const == T* const 、、Error
125  // error: passing `const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >'
126  // as `this' argument of `__gnu_cxx::__normal_iterator<_Iterator, _Container>& __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator++()
127  // [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]' discards qualifiers|
128          cout  <<   "  *iVec.begin():  "   <<   * iVec.begin()  <<   " \n "  ;
129          vector < int > ::const_iterator cit  =  iVec.begin() ; // vector<T>::const_iterator == const T*
130           // *cit = 1 ; // 错误! *cit(所指物)是const
131  // error: assignment of read-only location|
132           ++ cit ; // 没有问题,改变 cit ,指向下一个所指物 
133           //  -------------------------------------------
134          TextBlock tb( " Hello " ) ;
135          cout  <<   "   "   <<  tb[ 0 <<   " \n "  ;
136           const  TextBlock ctb( " Hello " ) ;
137          cout  <<   "   "   <<  ctb[ 0 <<   " \n "  ;
138          cout  <<   "  print_0(tb) ; \n "  ;
139          print_0(tb) ;
140      }
141  } // namespace testItem03
142  //  ====================================================================
143  //  --- 条款04:确定对象被使用前先被初始化 
144  //  注意:
145  //  1    为内置型对象进行手工的初始化,因为C++ 不保证初始化它们
146  //  2    构造函数最好使用成员初值列表初始化成员变量( member initializatiob list) ,
147  //       而不要在构造函数本体内使用赋值操作(assignment)。初始列表列出的成员变量,其排列次序应该跟
148  //       它们在class 中的声明次序相同。(而class 中的声明次序应该符合逻辑)
149  //  3    为免除“跨编译单元之初始化次序”问题,请以local static 对象替换 non-local static 对象。
150  //  4    对于大多数类型而已,比起先调用default构造函数日后再调用copy assignment操作符,单只调用
151  //       一次构造函数是比较高效的,有时甚至高效得多。(而对于内置类型基本一样,差不多)
152  //       在“初始化次序不确定性”(这对不同编译但愿所定义的non-local static对象是一种折磨)氛围下
153  //       加强你的设计,你可以考虑 以上 3 点的策略 non-local static -->> local static转化 !!!
154  namespace  testItem04
155  {
156       class  PhoneNumber {} ;  //  .
157       class  ABEntry
158      {
159       private :
160           string  name_ ;
161           string  address_ ;
162          std::list < PhoneNumber >  phones_ ;
163           int      numTimesConculted ;
164       public :
165          ABEntry() ;
166          ABEntry( const   string &  name , const   string &  addr ,\
167                   const  list < PhoneNumber >  phones )
168          : name_(name) ,address_(addr) ,phones_(phones) ,\
169            numTimesConculted( 0 // 初始化列表初始化 data member
170          {}  //  主体为空 记住根据class定义data member次序初始化 .
171           /*
172          {
173              name_ = name ;  //这些都是赋值--assignments
174              address_ = addr ;//而不是 初始化--initilizations
175              phones_ = phones ;
176              numTimesConculted = 0 ;
177          }  */
178      } ;
179      ABEntry::ABEntry():name_() ,address_() ,phones_() ,numTimesConculted( 0 )
180      {} //  记住根据class定义data member次序初始化 .
181       //  ----------------------------------
182       //  -------- one.h ---------- //   // 多编译单元情况
183       class  FileSystem
184      {
185       public :
186          FileSystem() :numDisks_( 0 ) {} // ..
187          FileSystem( int  numDisks) :numDisks_(numDisks) {} // ..
188           //  
189          std::size_t numDisks()  const  ; // 众多成员函数之一
190           //  
191       private :
192           int  numDisks_ ; //  
193      } ;
194      std::size_t FileSystem::numDisks()  const
195      {  return  numDisks_ ; } //   // 多编译单元情况
196       // FileSystem tfs ;  // okokok
197       //  -------- theOther.h ---------- //   // 多编译单元情况
198      FileSystem tfs_non_local_static ; // 预备给客户使用对象--
199       // extern FileSystem tfs_non_local_static ; // 预备给客户使用对象--the file system  // 多文件(编译单元)
200       //  .
201      FileSystem &  tfs_local_static() ; // 声明函数 
202       class  Directory
203      {
204       private :
205           string  dir_ ;
206       public :
207           explicit  Directory( string  dir) ;
208           //  
209      } ;
210      size_t handleNumDisks(size_t num) {  /* . */ return  num ; } //  
211      Directory::Directory( string  dir) : dir_(dir)
212      {
213           //  
214           // size_t disks = tfs_non_local_static.numDisks() ; //  bad non-local static object
215          size_t disks  =  tfs_local_static().numDisks() ; // good local static object
216          handleNumDisks(disks) ;
217           //  
218      }
219       //  ---------------------------------------------------
220  //  3    为免除“跨编译单元之初始化次序”问题,请以local static 对象替换 non-local static 对象。
221      FileSystem & tfs_local_static()
222       // 这个函数用来替换tfs对象:它在FileSystem class 中可能是一个static
223      { // 定义并初始化一个local static对象,返回一个reference指向上述对象 
224           static  FileSystem fs ;
225           return  fs ;
226      }
227  } // namespace testItem04
228  //  === 二、构造/析构/赋值运算 ============================================
229  //  ====================================================================
230  //  --- 条款05:了解C++ 默默编写并调用的哪些函数:
231  //      (默认)构造函数,析构函数,赋值函数,复制构造函数
232  //  注意:
233  //  1    编译期可以暗自为class 创建 default 构造函数,copy构造函数,copy assignment
234  //       操作符,以及析构函数 
235  namespace  testItem05
236  { //  ..
237  }
238  //  ====================================================================


你可能感兴趣的:(Effective C++ 学习历程001)