虛函數(1)
一、C++為什么引入虛函數,虛函數有哪些用途?
1.非虛的世界
對象的自恰性:對同樣的函數調用,每個對象都會做出恰當的響應.
b. 通過指向子類對象的基類指針調用函數:
只能調用基類的成員函數,雖然指針指向子類對象.
一旦調用子類所特有的成員函數,將引發編譯錯誤.
c.通過指向基類對象的子真調用函數:
可以調用子類的成員函數,盡管指針指向基類對象.
直接或簡介地訪問子類的成員變量,后果不可預知
d.名字隱藏
子類的成員函數隱藏基類的同名的成員函數.
#include <iostream> #include <string> using namespace std; class Base { public: Base(int data = 0):m_data(data){} void print(void) const { cout << m_data << endl; } private: int m_data; }; class Derived:public Base { public: Derived(int data,const string& info): Base(data),m_info(info){} void show(void) const { print(); cout << m_info << endl; } void foo(void) { cout << "Derived::foo(void)" << endl; // m_info = "abc"; } private: string m_info; }; int main(void) { Base b(100); Derived *pd = static_cast<Derived*>(&b); /*子類的指針指向父類*/ /*pd->show();*/ /*這里可以成功調用但是調用的結果是未定義的 因為編譯器在調用的時候只看類型. */ pd = NULL; pd->foo(); //這里是可以的,因為編譯器在編譯的時候只看類型. ((Derived*)0)->foo(); /*函數并不存在于對象中,調用成員函數的時候, 只要調用的類型是對的,就可以根據類型調用相應的 成員函數.但是這種情況之下不能訪問成員變量*/ return 0; }
2. 虛函數和名字隱藏
class 類名
{
virtual 返回類型 函數名(形參表){...}
}
的成員函數,稱為虛函數或方法
覆蓋:
如果子類的成員函數和基類的虛函數具有相同的函數原型,那么該成員
函數就也是虛函數,無論其是否有virtual關鍵字,且對基類的虛函數
構成覆蓋.
還有一種就是如果沒有virtual的時候,只要函數名相同就會形成覆蓋.
3.多態
如果子類提供了對基類虛函數的有效覆蓋,那么通過一個指向子類對象的基類指針,
或者引用子類對象的基類引用,調用該虛函數,實際被調用的將是子類中覆蓋
版本,而非基類中的原始,這種現象稱之為多態.
多態的重要意義在于,一般的情況下,調用哪個類的成員函數是由調用者指針或引用
本身的類型決定的,而當多態發生的時候,調用哪個類的成員函數則
完全由調動者指針或引用的實際目標對象的類型決定的.
4.有效的虛函數的覆蓋要滿足如下的條件
該函數必須是成員函數,既不能是全局函數也不能是靜態成員函數.
該函數必須在基類中用vitual關鍵字聲明為虛函數
覆蓋版本與基類版本必須擁有完全相同的簽名,即是函數名,行參表和常屬性嚴格一致.
如果基類版本返回基本數據類型,那么覆蓋版本必須返回相同的類型的數據.
如果基類版本返回類類型對象的指針或引用,那么覆蓋版本可以返回
其子類類型對象的指針或引用.
浙公網安備 33010602011771號