c++運算符重載和虛函數


運算符重載與虛函數

單目運算符

接下來都以AClass作為一個類例子介紹

AClass{

int var

}

  • 區分后置++與前置++
  • AClass operator ++ () ++前置 一般設計為返回引用 這樣的話可以將其作為左值(自然也可以作為右值,會調用該類的拷貝構造函數) ++class = ...
  • AClass operator ++ (int) 后置++ 一般設計返回一個舊的類 獲得的是歷史版本,所含有的int形參是用作區分類型的,並無實際含義
  • 由於一個__單變量__的構造函數可被視為__強制類型轉換函數__
多目運算符
  • AClass & operator (const & Aclass a){ ... }

  • 因此如果該類的構造函數滿足把int變成這個類,你甚至可以這么寫

  • int a; AClass A; A = A + a

函數的默認形參值只能寫在聲明里,不能寫在定義里

  • 對於<< 的重載方式,定義友元函數
  • frend ostream & operator << (ostream & out, const ...)
  • 這樣ostream就能訪問該類的私有成員了
  • 注意!插入運算符<< 的返回值要是這個out的引用
  • {... return & out} 這樣就可以實現一直<<插入的神奇功能(請自己思考為什么, 提示:返回引用等於又把自己拿出來用了)

虛函數

覆蓋 override 重載 overload

虛函數基本語法

巧妙的覆蓋方式

  • 虛函數的聲明
  • virtual 函數類型 函數名(形參表){
  • 函數內容}
  • 可以在基類中聲明虛函數,則子類中的相關函數會被同樣被認為為虛函數
  • 並且在創建基類指針指向一個子類時
  • 調用該基類指針的這個虛函數
  • 該指針會順着找到子類的這個函數並且運行
  • 體現了程序運行過程中的__動態多態特性__
  • 例子
class Base{
    virtual void func(){
        cout << "Base" << endl;
    }
}
class Base1{
    void func(){
        cout << "Base1" << endl;
    }
}
class Base2: public base{
    void func(){
        cout << "Base2" << endl;
    }
}
void display(base * ptr)
int main(){
    Base1 b1;
    Base2 b2;
    Base * ptr1 = b1;
    Base * ptr2 = b2;
    display(ptr1);
    display(ptr2);
}

/*
輸出結果
Base1
Base2

*/

typeid

  • typeid(ptr).name() 此處ptr為一個指針,返回這個指針的類型
  • typeid(* ptr).name() 此處返回的是ptr指向對象的類型
  • 如果你對上面的ptr1 ptr2進行第一種操作返回類型為base
  • 但是如果做第二種操作返回是base1和base2
虛析構函數

可能你想不到,析構函數也很虛

  • 析構函數和構造函數是不會繼承的
  • 加上析構函數在組合關系中會按拓撲序反向調用
  • 那么要虛構函數的理由就是有時候你需要動態刪除由__基類指針指向的派生類__
  • 沒有虛函數你就只能把指針指向的東西__當成基類__,而其本身是__派生類__,進行了析構
  • 那么這樣子你就會漏去除一些內容
  • 這樣很不優雅(你可以想象內存會出現什么嚴重后果)
舉個栗子!
  • 比如我這么引用Base *b = new Derived()

derived 代指派生類

  • 那么我們的b一調用delete就涼涼了
  • delete b
  • 編譯器高興地把b指向的地方當做Base刪掉了
  • 仔細想想,Derived的構造函數被調用了,但是析構函數被忽略了,(原因是我換了一個指針引用)
解決方法(就是虛析構函數)
  • 給基類的析構函數前面加個virtual關鍵字
  • 那么這就給這個東西加上了__動態多態性!__
  • 然后編譯器就會跑去先調用一下Derived類的析構函數然后再調用Base的

純虛函數

很純潔的函數

  • 想想,概念都是完美的東西,那么純虛函數就是用來描述概念的
純虛函數語法
  • virtual 類型 函數名(參數列表) = 0
  • 正如你所見,它沒有函數體(非常的純)
  • 帶有純虛函數的類稱之為__抽象類__(另一個叫做__具體類__)
抽象類
概念及理念
  • 為啥需要抽象類
  • 由於c++沒有接口功能,那么這個純虛函數便是用作接口功能
  • 底下的派生類只有將所有純虛函數全部實現才能稱之為_具體類_
  • 也可以用另一種觀點來看,就是為所有派生類定義了規范
  • 這是一種面向接口的設計方式,也是面向抽象類的設計
  • 抽象類的設計需要非常謹慎,因為派生類需要圍繞抽象類進行設計
  • 那么如果沒有設計好抽象類,那么容易帶偏派生類
幾個小規定
  • 抽象類只能用作基類
  • 不能聲明抽象類的對象
    • 原因:抽象類中具有純虛函數,而這個函數按語法可調用,但是這個函數沒有實現,因而為了解決這個問題直接禁止了抽象類的聲明
  • 構造函數不能夠是虛函數,析構函數可以是虛函數
  • 可以定義抽象類的指針


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM