培養正規的、大氣的編程習慣編程
1、C++簡介函數
1,分類佈局
C++分爲基於對象和麪向對象兩種優化
基於對象是指簡單的類定義,數據封裝,沒有類與類的聯繫,面對的是單一class的設計。又可細分爲不帶指針的類和帶指針的類this
面向對象是指包含類與類之間的聯繫,面對的是多重class的設計。主要包括繼承,複合,委託等。spa
2,歷史和演化設計
1983年開發指針
重要版本:C++(98) 1.0 --> C++(03) TR1 --> C++(11) 2.0 --> C++(14)code
3,經典書籍對象
1,《C++ Primer》Fifth Edition ---Stanley B.Lippman ----> C++語言的發明者
2,《The C++ Programming Language》 Fourth Edition ---Bjarne Stroustrup -----> C++第一個編譯器的做者
3,《Effective C++》Scott Meyers
4,《Effective C++》中文版 侯捷
5,《The C++ Standard Library》Second Edition --- Nicdlai M.Josuttiy
6,《STL源碼剖析》侯捷
2、不成文規範
1,防衛式聲明
對於大型程序每每有許多文件,在頭文件相互包含時容易形成重複定義,採用如下的宏定義形式可避免重複定義的錯誤。
#ifndef __COMPLEX__ #define __COMPLEX__ // write your code #endif
2,頭文件的佈局--三段式
前置聲明-類聲明-類定義
3,類模板--避免了因爲變量類型不一樣編寫大量冗餘的代碼
1 template<typename T> 2 complex<double> c1(2.5, 1.5) // complex類中的T都替換成double 3 complex<int> c2(2,6) // complex類中的T都替換成int
4,inline
1,簡單的函數可在類體中直接定義,默認爲inline
2,在類體外定義的函數須要顯式聲明inline
3,inline只是建議編譯器優化,可是對於複雜的函數編譯器沒有能力優化
5,構造函數 complex(double r = 0, double i = 0):re(r),im(i){}
1,建立對象時,自動調用
2,參數可設置默認值
3,採用初值列初始化,比大括號中賦值效率高,構造函數特有初始化方式
4,沒有返回值
6,建立對象的三種方法
1,complex c1(2, 1); // 採用傳入的2,1進行初始化
2,complex c2; // 採用默認值0,0進行初始化
3,complex *p = new complex(4); // new申請一塊內存空間,返回首地址,採用4,0進行初始化
7,不帶指針的類多半不須要析構函數
8,構造函數能夠有不少個--重載
反例--如下兩個構造函數不能夠同時聲明,由於假如實例化一個對象complex c1;編譯器不知道選擇哪個構造函數
complex(double r = 0, double i = 0):re(r),im(i){} complex():re(0),im(0){}
9,構造函數放在private區域--singleton
1 class A 2 { 3 public: 4 static A& getInstance(); 5 setup(){...} 6 private: 7 A(); 8 A(const A& rhs); 9 ... 10 } 11 12 A& A::getInstance() 13 { 14 static A a; 15 return a; 16 }
10,常量成員函數
以下函數只是取數據而不會改變數據,須要加上const
double real() const {return re;}
若是不加const,說明使用者能夠改變re,而使用者在建立對象時加const,說明是常量,不能夠改變,先後矛盾,編譯會不經過
1 const complex c1(2,1); 2 cout << c1.real(); 3 cout << c1.image();
11,參數傳遞 pass by value vs. pass by reference (to const)
1,儘可能pass by reference (to const)
2,pass by value可能數據量大,傳輸速度慢
3,pass by reference傳輸的是一個指針,傳輸速度快
4,傳引用一旦被修改會影響到原變量,此時加const表示不能夠修改
complex& operator += (const complex&);
12,返回值傳遞 return by value vs. return by reference (to const)
1,儘可能return by reference (to const)
13,友元--直接拿數據
1,缺點:破壞了封裝性
2,優勢:獲取數據更快
3,疑問:第四講26:50
侯傑老師講友元函數破壞了封裝性可是獲取數據更快,因此doapl設置成了friend,我在想doapl若是隻是在類的方法裏調用的話,doapl設置成private是否是更好呢,既不破壞封裝性又能夠直接拿數據 (直接拿數據的意思是直接使用re,im)
Ans:因爲其餘地方也有可能用到
14,相同class的各個objects互爲友元
1 public: 2 int func(const complex& param) 3 { return param.re + param.im } 4 usage: 5 { 6 complex c1(2,1); 7 complex c2; 8 c2.func(c1); 9 }
15,指導原則
1,數據都放在private裏
2,參數儘量傳reference
3,返回值儘量傳reference
4,參數考慮是否加const
5,構造函數使用初始列
16,什麼狀況下可使用 return by reference
函數外部傳入的變量返回可使用,函數內部定義的變量返回不可使用,關鍵點在於變量的做用域,函數內部的變量執行完成被銷燬了就不存在地址了
1 inline complex& // 接受的是value的地址 2 __doapl(complex* ths, const complex& r) // 傳遞者無需知道接收者是以reference形式接受 3 { 4 ths->re += r.re; 5 ths->im += r.im; 6 return *ths; // 返回的是value 7 } 8 inline complex& 9 complex::operator += (const complex& r) 10 { 11 return __doapl(this, r); 12 }
17,操做符重載
1,成員函數--全部的成員函數都帶着一個隱藏的參數this,指向調用者
此處返回值能夠是void,可是不適用於c1 += c2 += c3
1 inline complex& 2 complex::operator += (const complex& r) 3 { 4 return __doapl(this, r); 5 }
2,非成員函數
1 c2 = c1 + c2; 2 inline complex 3 operator + (const complex& x, const complex& y) 4 { 5 return complex(real(x) + real(y),imag(x)+imag(y)); 6 } 7 c2 = c1 + 5; 8 inline complex 9 operator + (const complex& x, double y) 10 { 11 return complex(real(x) + y, imag(x)); 12 } 13 c2 = 7 + c1; 14 inline complex 15 operator + (double x, const complex& y) 16 { 17 return complex(x + real(y), imag(y)); 18 }
此處返回值類型絕對不能夠是reference,因爲不是外部傳入的變量 建立臨時對象complex(),下一行即失效---typename() 定義成非成員函數,int+c1調用的是double+c2的狀況,int自動類型轉換爲double 當咱們把運算符定義成成員函數時,它的左側運算對象必須是運算符所屬類的一個對象 ----------------------------------------------------------------------------------------------------------------------- 內置類型裏面+一般設計成非成員函數,+=一般設置成成員函數。咱們自定義類型的時候, +=和+模仿內置類型會符合用戶一直以來的習慣