從複數類實現中看到精髓--面向對象高級開發學習系列

聲明

學習材料: 侯捷老師 極客band的教程
筆記使用VScode寫markdown
用sublime編譯,因爲VScode對於中文路徑編譯有問題
用csdn來作爲快速圖牀

inline和宏

inline和宏差不多,方法直接寫在定義的地方是inline
會很快,寫在外面用inline關鍵字來標識,具體是否
inline取決於編譯器實現

public,private

數據和私有數據處理一般放在private
public放給外界使用的接口

可以交錯寫,不一定只寫成兩段

構造函數

  • 可以默認值,當然其他函數也可以這樣
  • 一般使用complex(double r=0,double i=0):re(r),im(i){}初始化列 裏面寫,這樣寫得很大氣(在初始化列初始化)
  • 構建賦值由聲明順序決定
  • 沒有返回類型—不過曾經學jni發現是返回類對象的指針
  • 可以有多個構造函數,可以重載(常用於構造函數),編譯器會編碼成不同的東西

但是以下兩種會是編譯器不知道怎麼構造而發生衝突

public:
    complex(double r = 0, double i = 0)
        : re (r), im (i)
    { }
    complex () : re(0), im(0) { }

{
    // 下面會導致ambiguous
    complex a;
    complex b();
}
  • singleton單例設計模式把構造函數寫在private(老師說暫時不深入)

不帶指針的類和帶指針的類

不帶指針的類多半不用寫析構函數

const member functions(常量成員函數)

不改變數據內容的,就加const關鍵字

一般只是返回數據

不寫會怎樣,看老師的例子,老師說很重要

正規,大師寫法,魯棒性更高

double real () const { return re; }

{
    const complex c1(2,1);
// 如果前面方法沒有用const,而你定義的c1是const
// 這樣你使用下面的輸出編譯器會報錯
// 因爲它以爲你可能會改變c1中的值,所以不準
    cout<< c1.real();
    cout<< c1.imag();
}

pass by value vs. pass by reference

傳值可能在size很大的時候會導致耗時很多

引用就好很多

C語言有指針傳遞

老師說引用的底部其實就是指針 4個字節

當然如果char 1個字節,也可以直接傳值,但是爲了統一
還是用引用比較好

然後就是如果不想別人改變你內容,你可以用
你改了就編譯不過

complex& operator += (const complex&);

return by value vs. return by reference

爲了效率,有些東西要成爲習慣

返回值也儘量使用引用,如上面代碼

如果要返回臨時變量就不能傳引用,因爲臨時變量在
函數結束之後自己會消亡掉

friend(友元)

友元可以取得private成員

朋友雖然打破了封裝,但是可以直接引用數據,
函數調用獲取數據就慢了

相同的class的各個objects互爲友元

class complex{
public:

    // 這裏沒有通過函數拿,而是直接拿數據
    int func(const complex& param)
    { return param.re + param.im; }
}

老師說檢查學生寫的類注意點

  1. 數據在private
  2. 參數儘可能引用,看情況const
  3. 返回值儘可能引用傳遞
  4. body本體中應該加const就要加(別人要不要用const都可以了)
  5. 初始化賦值儘量使用,儘量不要很晚了在{}內賦值

操作符重載1–成員函數_有this

  • C++裏面操作符就相當於一個函數,而C語言不是
  • 寫個plus函數不好,所以C++容許你重載+
  • 誰調用我,誰就是this(寫代碼看不到this傳參),任何成員函數都隱藏了this

return by reference

傳參者無需知道接收者是以reference形式接收!

傳參者無需知道接收者是以reference形式接收,你可以用reference接收,也可以用值傳遞接收

突然讓我想到上次慘敗的tx面試,函數傳指針和引用有什麼區別,現在看了侯捷老師的講解才知道這麼精妙
就是定義爲指針的話,傳遞者也必須知道自己要傳遞的是指針,而如果是reference的話,傳遞者只需要知道自己傳遞一個對象就行了,絕妙的講解啊

連串賦值

還因爲有連串賦值,所以+=的返回值不設計成爲void,而是complex&

上面3個小節對應的代碼和圖片看下面

inline complex&
__doapl(complex* ths, const complex& r)
{
    ...
    return *ths;
}


inline complex&
complex::operator += (const complex& r)
{
    return __doapl(this,r);
}

{
    complex c1(2,1);
    complex c2(5);

    c2 += c1;
    c3 += c2 += c1;
}

在這裏插入圖片描述

操作符重載2–非成員函數_無this

// 這裏 加 的返回值應該是對象,不能傳reference,否則傳出去一個指針,然後內存回收掉了,然後就很奇怪了
// c = a + b;
inline complex
operator + (const complex& x, const complex& y)
{
    return complex(real(x) + real(y),
                   imag(x) + imag(y));
}

臨時對象typename()

臨時對象typename(),生命很短,用完就沒了,上面那個函數中的complex()就是,臨時

關於直接返回引用的測試代碼

#include<bits/stdc++.h>
using namespace std;

// error: invalid initialization of reference of type 'int&' from expression of type 'const int'
//      return a;
//             ^

// 我試了一下,發現是不行的啊
// 等下,a變成了const int?!那應該就是說其實return之後應該也可以
// 變成int吧,難道老師說錯了,待會試試複數類的東西吧

// 後面複習的時候突然想到了爲什麼這裏不行了
// 因爲這裏a 已經變成了一個臨時變量了?
// 然後自己嘗試把const去掉,編譯成功了
// 所以就是說接受者const,傳參者隨意
// 但是如果接受者不const,傳參者不能const
// 這就是之前老師說的你設計的函數儘量加const!
// int & zheng(const int& a)
// {
//     return a;
// }
// 引用真香!!!!!

int & zheng(int& a)
{
    return a;
}

const int & zheng3(const int & a)
{
    return a;
}

int zheng2(const int& a)
{
    return a;
}

int main(){
    int a = 233;
    cout<< zheng(a)<<endl;
    cout<< zheng2(a)<<endl;
    cout<< zheng3(a)<<endl;

    return 0;
}

全部講解用到代碼

#ifndef __COMPLEX__
#define __COMPLEX__

// template<typename T>
class complex
{
public:
    complex (double r=0, double i=0)
        : re (r) ,im (i)
    { }

    complex& operator += (const complex&);
    double real () const { return re; }
    double imag () const { return im; }
private:
    double re, im;

    friend complex& __doapl (complex*,
                             const complex&);

};

inline complex&
__doapl(complex* ths, const complex& r)
{
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

inline complex &
complex::operator += (const complex & r)
{
    return __doapl (this, r);
}

inline complex
operator + (const complex& x, const complex& y)
{
    return complex (real(x) + real(y),
                    imag(x) + imag(y) );
}

inline complex
operator + (const complex& x, double y)
{
    return complex (real(x) + y, imag(x));
}

inline complex
operator + (double x, const complex& y)
{
    return complex (x + real(y), imag(y));
}

// 因爲不考慮 c1 << cout; 所以無法使用成員函數定義
// 因爲成員函數定義要用對象在左邊
#include <iostream.h>
ostream&
operator << (ostream& os, const complex& x)
{
    return os << '(' << real (x) << ','
              << imag (x) << ')';
}

#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章