之前不了解虛繼承,一度以為是和虛函式相關的東西,后來查了一下才知道是完全不相關的特性,特此記錄一下,
目錄- 虛函式
- 1. 寫法
- 2. 意義
- 3. 作用
- 4. 原理
- 虛繼承
- 1. 寫法
- 2. 意義
- 3. 作用
- 4. 原理
虛函式
1. 寫法
類中的成員函式,定義時在最左側加上virtual關鍵字,就被定義為了虛函式,
2. 意義
實作多型性,用父類指標指向子類物件時可以呼叫子類中的函式(前提:在父類中被定義為虛函式并在子類中進行了覆寫),
3. 作用
基類中的虛函式可以在子類中被重新定義,使用基類指標指向子類物件并呼叫虛函式時,呼叫到的會是子類中的函式,
子類中重新實作的虛函式,其引數串列需要與基類中的虛函式相同,virtual修飾符加不加都可以,
子類的子類仍然可以重新定義該虛函式,
#include <iostream>
using namespace std;
class A{
public:
virtual void func(){
cout << "I am A." << endl;
}
};
class B: public A{
public:
void func(){
cout << "I am B." << endl;
}
};
class C: public B{
public:
void func(){
cout << "I am C." << endl;
}
};
int main(int argc, const char * argv[]) {
A* pointer = new C();
pointer->func(); // 呼叫結果為: I am C.
return 0;
}
4. 原理
一旦類中有函式被定義為了虛函式,類就會擁有一個虛函式表,
虛函式表中,保存著一系列函式指標,指向這個類中的虛函式實際的起始地址,
為了能獲取到類的虛函式表,類的每個物件中就需要保存一個指標,指向自己的類的虛函式表(vtbl,也稱虛表),這個指標稱為虛函式表指標(vptr),
當使用基類指標指向子類物件并呼叫虛函式時,程式會通過物件的虛表指標去子類虛表中查找虛函式的實際地址,
也是因為這個原因,定義了虛函式的類的物件中會多一個4/8位元組(取決于32位/64位)的指標,存于變數的起始位置,
虛繼承
1. 寫法
一個型別在繼承另一個類時加上virtual修飾符,這個繼承就是一個虛繼承,其基類稱為虛基類,
2. 意義
虛繼承是為了解決C++中的多重繼承問題而存在的特性,
3. 作用
如果一個子類繼承了兩個不同的基類,這兩個類的繼承鏈中又有相同的基類,那么在子類中,公共基類會被繼承兩次,
比如菱形繼承:D繼承了B、C,B和C又都是A的子類,
這樣會導致兩個后果:
一是浪費空間,公共基類的成員存在兩份;
二是公共基類的成員來自兩條不同的繼承路徑,在使用時不能確定使用的是哪一個,因此存在二義性,
虛繼承可以解決這一問題,
由虛繼承方式被繼承的基類在子類的子類中只會存在一份記憶體結構,
4. 原理
虛繼承中,子類并不像普通繼承那樣擁有一份基類的記憶體結構,而是加了一個虛基類表指標指向虛基類,
當虛基類的子類被繼承時,虛基類表指標也會被繼承,
因此,當某個子類通過不同路徑繼承了同一個虛基類時,該子類的記憶體中只會存在一份虛基類的拷貝,避免了沖突,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/218789.html
標籤:C++
