void main() { }

Hello ,world !

常用链接

统计

最新评论

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 // ====================================================================


posted on 2010-05-27 17:12 only 阅读(224) 评论(0)  编辑 收藏 引用 所属分类: 琐碎编程


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理