自從大一下接觸C++面向?qū)ο蟪绦蛟O(shè)計(jì),我就對(duì)一直在學(xué)習(xí)C++ 這門(mén)語(yǔ)言,當(dāng)然了也一直很喜歡C++。在之前剛剛開(kāi)始C語(yǔ)言程序設(shè)計(jì)時(shí),自己還不喜歡編程這門(mén)學(xué)問(wèn)。后來(lái),慢慢喜歡上編程,正是跟隨著C++ 語(yǔ)言的慢慢學(xué)習(xí)與積累的。嗯,我很喜歡C++這門(mén)語(yǔ)言!
那就從一本摯愛(ài)的圖書(shū)《Effective C++ 》開(kāi)始吧,也當(dāng)是給“Effective C++ 學(xué)習(xí)歷程”做個(gè)簡(jiǎn)單的開(kāi)始。
1 namespace testItem01
2 {
3 }//namespace testItem01
4 // ====================================================================
5 // --- 條款02:盡量以const,enum,inline替換 #define
6 // 注意:
7 // 1 對(duì)于單純變量,最好以const 對(duì)象或是 enumS 替換 #defineS 。。。
8 // 2 對(duì)于形似函數(shù)的 宏(mactos),最好改用inline(結(jié)合 template) 函數(shù)替換 #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>b ? 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 導(dǎo)致的錯(cuò)誤
..
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可以幫助編譯器偵測(cè)出錯(cuò)誤語(yǔ)法。const可被施加于任何作用域內(nèi)的
50 // 對(duì)象、函數(shù)參數(shù)、函數(shù)返回類型、成員函數(shù)本體 
51 // 2 編譯器強(qiáng)制執(zhí)行(實(shí)施)bitwise constness 。但你編寫(xiě)程序時(shí)應(yīng)該使用“概念上的常量性”(conceptual constness)
52 // 3 當(dāng) const 和 non-const成員函數(shù)有著實(shí)質(zhì)等價(jià)的實(shí)現(xiàn)時(shí),令non-const版本去調(diào)用const版本可避免代碼重復(fù) 。
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 跳轉(zhuǎn) const 版本 + 過(guò)程轉(zhuǎn)換 
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" ; }//調(diào)用const char& operator [](std::size_t pos) const
88 // ------------關(guān)鍵字 mutable mutable mutable ---------
89 class CTextBlock
90 {
91 private:
92 char* pText ;
93 mutable size_t textLength ;//可以在 const成員函數(shù)改變?cè)摮蓡T變量 
94 mutable bool lengthIsValid ;//可以在 const成員函數(shù)改變?cè)摮蓡T變量 
95 public:
96 size_t length() const ;
97 // 
98 } ;
99 size_t CTextBlock::length() const//可以在 const成員函數(shù)改變?cè)摮蓡T變量 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 ; // 沒(méi)有問(wèn)題,實(shí)際改變it所指物,但違背正常邏輯 
124 //++it ; //錯(cuò)誤!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 ;//錯(cuò)誤! *cit(所指物)是const
131 //error: assignment of read-only location|
132 ++cit ;//沒(méi)有問(wèn)題,改變 cit ,指向下一個(gè)所指物 
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:確定對(duì)象被使用前先被初始化 
144 // 注意:
145 // 1 為內(nèi)置型對(duì)象進(jìn)行手工的初始化,因?yàn)镃++ 不保證初始化它們
146 // 2 構(gòu)造函數(shù)最好使用成員初值列表初始化成員變量( member initializatiob list) ,
147 // 而不要在構(gòu)造函數(shù)本體內(nèi)使用賦值操作(assignment)。初始列表列出的成員變量,其排列次序應(yīng)該跟
148 // 它們?cè)赾lass 中的聲明次序相同。(而class 中的聲明次序應(yīng)該符合邏輯)
149 // 3 為免除“跨編譯單元之初始化次序”問(wèn)題,請(qǐng)以local static 對(duì)象替換 non-local static 對(duì)象。
150 // 4 對(duì)于大多數(shù)類型而已,比起先調(diào)用default構(gòu)造函數(shù)日后再調(diào)用copy assignment操作符,單只調(diào)用
151 // 一次構(gòu)造函數(shù)是比較高效的,有時(shí)甚至高效得多。(而對(duì)于內(nèi)置類型基本一樣,差不多)
152 // 在“初始化次序不確定性”(這對(duì)不同編譯但愿所定義的non-local static對(duì)象是一種折磨)氛圍下
153 // 加強(qiáng)你的設(shè)計(jì),你可以考慮 以上 3 點(diǎn)的策略
non-local static -->> local static轉(zhuǎn)化 !!!
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 {} // 主體為空
記住根據(jù)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 {}//
記住根據(jù)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 ;//眾多成員函數(shù)之一
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 ;//預(yù)備給客戶使用對(duì)象--
199 //extern FileSystem tfs_non_local_static ;//預(yù)備給客戶使用對(duì)象--the file system //多文件(編譯單元)
200 //
.
201 FileSystem& tfs_local_static() ;//聲明函數(shù) 
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 為免除“跨編譯單元之初始化次序”問(wèn)題,請(qǐng)以local static 對(duì)象替換 non-local static 對(duì)象。
221 FileSystem&tfs_local_static()
222 //這個(gè)函數(shù)用來(lái)替換tfs對(duì)象:它在FileSystem class 中可能是一個(gè)static
223 {//定義并初始化一個(gè)local static對(duì)象,返回一個(gè)reference指向上述對(duì)象 
224 static FileSystem fs ;
225 return fs ;
226 }
227 }//namespace testItem04
228 // === 二、構(gòu)造/析構(gòu)/賦值運(yùn)算 ============================================
229 // ====================================================================
230 // --- 條款05:了解C++ 默默編寫(xiě)并調(diào)用的哪些函數(shù):
231 // (默認(rèn))構(gòu)造函數(shù),析構(gòu)函數(shù),賦值函數(shù),復(fù)制構(gòu)造函數(shù)
232 // 注意:
233 // 1 編譯期可以暗自為class 創(chuàng)建 default 構(gòu)造函數(shù),copy構(gòu)造函數(shù),copy assignment
234 // 操作符,以及析構(gòu)函數(shù) 
235 namespace testItem05
236 {//
..
237 }
238 // ====================================================================