C++ 面向物件程式設計之多型理解
阿新 • • 發佈:2018-12-16
#include <iostream> using namespace std; /* 多型的理解 其中面向物件四大特徵之一 其餘為封裝 抽象 繼承 可以簡單概括為“一個介面 多種方法” 1.其中C++多型性體現在編譯期多型和執行期多型 編譯期多型如模板函式,其中函式過載與多型無關。 執行期多型則是具體引用的物件在執行時才可以確定,通常主要通過虛擬函式來實現,並且一定要有繼承關係。 有虛擬函式,則可以重寫這個函式,這裡要注意不是過載,也不是覆蓋(父類的方法前面無virtual)。 2.理解(parent* pa = new child();)定義一個父類指標,指向子類物件,呼叫函式在執行期間 動態繫結到指標實際所指的物件。 3.Tuna *pTuna = new Tuna;// 使用new 在自由儲存區例項化 通過指標呼叫delete 不會呼叫派生類的解構函式 可將基類解構函式宣告為虛擬函式 4.Tuna MyDinner;//區域性變數方式在棧中例項化 5.編譯器為實現了虛擬函式的基類和重寫的這個函式的派生類分別建立一個虛擬函式表 (VFT,virtual function table)。base類和derived類都有自己的虛擬函式表, 例項化這些類的物件時,將建立一個隱藏的指標(VFT*),他指向相應的VFT,可將其視為一個 包含函式指標的靜態陣列,每個指標指向相應虛擬函式。 6.抽象基類(ABC abstract base class)為不能被例項化的基類,用來派生出其他類。 講指標或者引用的型別指定為抽象基類,宣告所有派生類都必須實現其函式。 */ class parent { public: parent() {} // 父類的虛擬函式 virtual void eat() { std::cout << "Parent eat." << std::endl; } // 注意這個並不是虛擬函式!!! void drink() { std::cout << "Parent drink." << std::endl; } }; class child : public parent { public: child() {} // 子類重寫了父類的虛擬函式 void eat() { std::cout << "Child eat." << std::endl; } // 子類覆蓋了父類的函式,注意由於父類的這個函式 // 並不是虛擬函式,所以不存在繼承後重寫的說法 void drink() { std::cout << "Parent drink." << std::endl; } // 子類特有的函式 void childLove() { std::cout << "Child love playing." << std::endl; } }; int main() { parent* pa = new child(); pa->eat(); // 執行期多型的體現!!! pa->drink(); // 這裡呼叫的還是父類的drink,所以並不是多型!!! // pa->childLove(); // 編譯出錯,父類的指標不能呼叫父類沒有的函式 return 0; }
多型的理解 其中面向物件四大特徵之一 其餘為封裝 抽象 繼承 可以簡單概括為“一個介面 多種方法” 1.其中C++多型性體現在編譯期多型和執行期多型 編譯期多型如模板函式,其中函式過載與多型無關。 執行期多型則是具體引用的物件在執行時才可以確定,通常主要通過虛擬函式來實現,並且一定要有繼承關係。 有虛擬函式,則可以重寫這個函式,這裡要注意不是過載,也不是覆蓋(父類的方法前面無virtual)。 2.理解(parent* pa = new child();)定義一個父類指標,指向子類物件,呼叫函式在執行期間 動態繫結到指標實際所指的物件。 3.Tuna *pTuna = new Tuna;// 使用new 在自由儲存區例項化 通過指標呼叫delete 不會呼叫派生類的解構函式 可將基類解構函式宣告為虛擬函式 4.Tuna MyDinner;//區域性變數方式在棧中例項化 5.編譯器為實現了虛擬函式的基類和重寫的這個函式的派生類分別建立一個虛擬函式表 (VFT,virtual function table)。base類和derived類都有自己的虛擬函式表, 例項化這些類的物件時,將建立一個隱藏的指標(VFT*),他指向相應的VFT,可將其視為一個 包含函式指標的靜態陣列,每個指標指向相應虛擬函式。 6.抽象基類(ABC abstract base class)為不能被例項化的基類,用來派生出其他類。 講指標或者引用的型別指定為抽象基類,宣告所有派生類都必須實現其函式。