多型定義:多種形式或形態
多型分類
靜態多型:在編譯期間完成,編譯器根據函式實參的型別推斷出要呼叫哪個函式。
在這裡我們只說函式過載,泛型程式設計在後面再進行介紹。
函式過載的條件
(1)在同一作用域
(2)函式名相同,引數不同
(3)返回值可以不同
動態多型;在程式執行期間判斷所引用物件的實際型別,根據其實際型別呼叫相應的方法。
實現動態多型的條件
1.必須是虛函式
關於虛函式
使用virtual關鍵字修飾類的成員函式時,指明該函式為虛函式,派生類必須對其進行重寫。
將基類的某乙個成員函式定義為虛函式,在派生類中該函式始終保持虛函式的特
性。 只有類的非靜態成員函式才能定義為虛函式,靜態成員函式不能定義為虛函式。
重寫也稱覆蓋,函式重寫的條件
(1)不在同一作用域(分別在基類和派生類)
(2)函式原型相同(函式名相同,引數相同,返回值相同)
(3)基類函式必須有virtual關鍵字
(4)訪問修飾符可以不同
2.通過基類型別的引用或者指標呼叫虛函式
虛表:
對於有虛函式的類,編譯器都會維護一張虛表,物件的前4個位元組就是指向虛表的指標。
下面來看乙個派生類將基類的虛函式重寫的例子,分析一下基類和派生類各自的虛函式表
單繼承派生類的虛函式表生成
1.先拷貝基類的虛函式表生成;
2.如果派生類重寫了基類的某個虛函式,就用派生類重寫後的虛函式替換相同偏移量位置的虛函式;
3.如果派生類有新增的虛函式,跟在基類的虛函式位址後面。
class b1
virtual
void fun1()
virtual
void fun2()
private:
int _b1;
};class b2
virtual
void fun3()
virtual
void fun4()
private:
int _b2;
};class d :public b1, public b2
virtual
void fun1()
virtual
void fun3()
virtual
void fun5()
private:
int _d;
};typedef
void(*pvtf)();
void printvpt(b1& b1, const
char* _table)
cout
<< endl;
}void printvpt(b2& b2, const
char* _table)
cout
<< endl;
}void test()
int main()
多繼承多型派生類物件模型
多繼承派生類的虛函式表生成
多繼承派生類虛函式的順序
1.如果派生類對b1中虛函式重寫,替換相同位置的虛函式;
2.如果派生類對b2中虛函式重寫,替換相同位置的虛函式;
3.如果派生類有自己新增的函式,放在第一張虛表之後。
多型下的菱形虛擬繼承
class b
virtual
void fun1()
virtual
void fun2()
private:
int _b;
};class c1:virtual
public b
virtual
void fun1()
virtual
void fun3()
private:
int _c1;
};class c2 :virtual
public b
virtual
void fun4()
private:
int _c2;
};class d :public c1, public c2
virtual
void fun1()
virtual
void fun4()
virtual
void fun5()
private:
int _d;
};typedef void(*pvtf)();
void printvpt(void* p, const
char* _table)
cout << endl;
}void test()
int main()
菱形虛擬繼承派生類的物件模型
派生類的虛表生成
成員函式的呼叫過程
1.是否為虛函式
2.若為虛函式,找虛表指標->虛函式位址->呼叫相應的虛函式;若為非虛函式,直接呼叫相應的函式。
C 多型之虛函式
問題 用基型別的指標指向派生類物件時,通過這個指標來訪問該物件,這是會出現訪問到的只是從基類繼承來的同名成員。解決方法 在基類中將這個同名函式宣告為虛函式,這樣就可以通過基型別的指標,訪問不同派生類的物件產生不同的行為,從而實現執行過程的多型。語法 virtual 函式型別 函式名 形參表 注意 必...
C 之虛函式和多型
1.虛函式 簡單的說,虛函式就是在函式原型前加上virtual關鍵字。函式一旦被宣告為虛函式,即使類在改寫它的時候沒有將其宣告為虛函式,它從該點的繼承層次結構中仍然是虛函式。如果基類中乙個函式被宣告為虛函式,在若干子類中有著不同的實現,那麼我們在建立若干子類的不同物件時,可以用基類的指標或者引用來指...
C 多型實現之虛方法
控制台應用程式中,新建乙個people類檔案,如下 using system using system.collections.generic using system.linq using system.text namespace 13多型 public string name 1.第一,將父類...