# 使用方法
* 在基類用virtual聲明成員函數為虛函數。這樣就可以在派生類中重新定義此函數,為它賦予新的功能,并能方便地被調用。在類外定義虛函數時,不必再加virtual。
* 在派生類中重新定義此函數,要求函數名、函數類型、函數參數個數和類型全部與基類的虛函數相同,并根據派生類的需要重新定義函數體。
* 當一個成員函數被聲明為虛函數后,其派生類中的同名函數都自動成為虛函數,派生類重新聲明該虛函數時,可以加virtual,也可以不加。
* 派生類中沒有對基類的虛函數重新定義,則派生類簡單地繼承其直接基類的虛函數。
* 定義一個指向基類對象的指針變量,并使它指向同一類族中需要調用該函數的對象。通過該指針變量調用此虛函數,此時調用的就是指針變量指向的對象的同名函數。
# 聲明格式
~~~
virtual 返回類型 函數名(形參列表);
~~~
# 作用
* 允許在派生類中重新定義與基類同名的函數,并且可以通過**基類指針**或**引用**來訪問基類和派生類中的同名函數。
* 同一類族中不同類的對象,對同一函數調用作出不同的響應。
# 虛函數與重載的區別
* 涵數重載處理的是同一層次上的同名函數問題,是橫向重載
* 虛函數處理的是不同派生層次上的同名函數問題,是縱向重載
* 同一類族的虛函數的首部是相同的,而函數重載時函數的首部是不同的(參數個數或類型不同)。
# 注意
* 只能用virtual聲明類的成員函數,使它成為虛函數,而不能將類外的普通函數聲明為虛函數。
* 一個成員函數被聲明為虛函數后,在同一類族中的類就不能再定義一個非virtual的但與該虛函數具有相同的參數(包括個數和類型)和函數返回值類型的同名函數。
* 如果該類會成為基類,且有成員函數在被繼承后,需要修改功能
* 如果是通過基類指針或引用去訪問的,則應當聲明為虛函數
# 虛表指針
* 當一個類帶有虛函數時,編譯系統會為該類構造一個虛函數表,它是一個指針數組,存放每個虛函數的入口地址。
* 而每當用多態類創建一個對象時,編譯器就會自動生成一個虛表指針
* 由構造函數正確對其初始化,使其指向該對象所屬類的虛函數表,最后將它放置在該多態類對象結構的開頭。
* C++采用的是絕對地址+偏移量的方法訪問虛函數的,這樣,在調用虛函數時,采用**滯后聯編**,就能夠映射到正確的虛函數了
* 如果將基類的析構函數聲明為虛函數時,由該基類所派生的所有派生類的析構函數也都自動成為虛函數
* 最好把基類的析構函數聲明為虛函數
* **構造函數不能聲明為虛函數**
- 介紹
- 編程設計語言
- 第一章 對C++的初步認識
- 1.2 最簡單的C++程序
- 1.3 C++對C的補充
- 1.3.1 return
- 1.3.2 輸入輸出流
- 1.3.3 putchar 和 getchar
- 1.3.4 用const定義常變量
- 1.3.5 函數原型聲明
- 1.3.6 內置函數
- 1.3.7 函數重載
- 1.3.8 函數模板
- 1.3.9 有默認值的參數
- 1.3.10 作用域
- 1.3.11 const修飾指針
- 1.3.12 引用
- 1.3.13 生命期
- 1.3.14 變量
- 1.3.15 字符串變量
- 第二章 類與對象
- 2.2 類的聲明和對象的定義
- 2.3 類的成員函數
- 第三章 關于類和對象的進一步討論
- 3.1 構造函數
- 3.1.1 對象的初始化
- 3.1.2 構造函數
- 3.2 析構函數
- 3.3調用析構函數和構造函數的順序
- 3.4 對象數組
- 3.5 對象指針
- 3.6 共享數據的保護
- 3.7 對象的建立與釋放
- 3.8 對象的賦值與復制
- 3.9 靜態成員
- 3.10 友元
- 3.11 類模板
- 第四章 運算符重載
- 數據類型轉換
- 運算符重載
- 重載流插入運算符和流提取運算符
- 第五章 繼承與派生
- 繼承與派生
- 第六章 多態性與虛函數
- 多態性
- 虛函數
- 純虛函數與抽象類