在本章主要簡述定義一個C++類的時候須要注意的細節,包括初始化列、操做符重載等。
實例講解代碼爲:ios
#ifndef COMPLEX_H #define COMPLEX_H #include<iostream> using std::ostream; using std::endl; using std::cin; using std::ends; using std::cout; class Complex { public: Complex(double, double); Complex(const Complex&); ~Complex(); double Get_re()const; double Get_img()const; Complex& operator +=(const Complex &); private: double re; double img; friend Complex& _add(Complex*, const Complex&);//因爲須要去除private元素,因此這設置爲友元,在調用一個函數的友元的時候,其也具有訪問另外一個對象private的能力 }; inline Complex::Complex(double re = 0, double img = 0) :re(re), img(img) { }; inline Complex::Complex(const Complex & comp) { this->re = comp.re; this->img = comp.img; cout << "調用了複製構造函數" << ends; } inline Complex::~Complex() { cout << "析構函數被調用" << endl; }; inline double Complex::Get_re() const { return re; }; inline double Complex::Get_img() const { return img; }; inline Complex& _add(Complex* ths, const Complex& plus_ele) { ths->re += plus_ele.re; ths->img += plus_ele.img; return(*ths); } //下面是包含this的重載運算符 inline Complex& Complex::operator +=(const Complex& plus_ele) { return _add(this, plus_ele); } //下面的都是不包含this的重載運算符 inline Complex operator +(const Complex & comp1, const Complex & comp2) { return Complex(comp1.Get_re() + comp2.Get_re(), comp1.Get_img() + comp2.Get_img()); } inline ostream& operator <<(ostream& os, const Complex& comp)//主要是爲了應對連續使用<<的狀況 { return os << comp.Get_re() << "+" << comp.Get_img()<<"i"; } inline void test_reference(Complex com) { cout << com << ends; } #endif // !COMPLEX_H
主要是爲了防止經過對象直接更改內部的值,固然能夠經過成員函數來更改其中的值,目的是增長類的封裝性。函數
若是使用一個值來傳遞的化咱們能夠定義一個全局函數接受一個Complex爲入口參數:this
inline void test_reference(Complex com) { cout << com << ends; }
同時在析構函數加入:spa
inline Complex::~Complex() { cout << "析構函數被調用" << endl; };
調用該函數的結果爲:
因此在傳值得時候建立了一個局部對象,使用複製構造函數度這個局部變量進行了初始化,在離開做用域的時候會銷燬這個局部變量,所以會調用析構函數,這也太麻煩了。code
主要緣由在於若是返回的是一個對象的話,這個對象是也是個臨時對象,將會在調用該函數的那一行後被析構。咱們加入一行對象
inline Complex test_reference1(Complex com) { return com; }
調用方式爲:繼承
Complex cmp1(1, 2); Complex cmp2(1,1); cmp2=test_reference1(cmp1);
結果爲:
兩次調用了析構函數與複製構造函數,緣由在於首先在傳遞參數的時候在函數內部構造了一個局部對象com,在返回一個對象後悔臨時再構建一個對象用於給cmp2賦值,隨後到下一行這個臨時變量就被析構函數析構了。ip
沒啥好說的,就是爲了防止在局部函數中更改了原始數據,若是確實有這個需求除外。內存
初始化列表初始化對象中的變量的做用是避免了初始化內部對象+賦值的操做,若是使用的是初始化列表,那麼其使用的是複製構造函數,這樣節省了大量的時間。ci
在進行操做符重載的時候能夠分爲兩類
一、包含this的成員函數(成員);
二、不包含this的非成員函數(全局);
這樣區別的理由是這個操做符的對象結果是否又被賦值給了這個操做符的入口參數?若是被賦值的對象爲入口參數變量如+=,-=等,那麼這個操做符重載應該是類的成員函數,例如cmp1+=cmp2的時候左側cmp1既是入口參數也是被賦值的對象,所以這個操做符應該被定義爲成員函數。若是這個操做符的結果並未賦值給入口參數變量,那麼應當定義爲全局運算符重載,如—,+等。
也就是說在一個對象處理另外一個類的private數據時候是有權限的:
inline double Complex::get_sum(const Complex& comp)const { return this->re + comp.re; };
comp.re是對象comp的private數據可是在this中居然能夠訪問!咱們可不能夠經過繼承一個類來訪問其私有數據來打破封裝性呢?很明顯不行,由於私有數據不被繼承(這句話不必定對,由於子內存上仍是繼承了只是不能直接訪問而已)。