C 虛函式和虛表

2021-07-14 06:46:45 字數 2077 閱讀 5134

一直對於c++的虛函式的概念比較模糊,今天上網查資料然後把虛擬繼承這一塊給搞懂了,給大家分享。

繼承是c++的一大特性,繼承是復用的重要手段,。通過繼承乙個類,繼承是型別(乙個類)之間的關係建模,共享父類的一些資源,但是有些資料是共享補了的,每個類都有自己要實現的東西,所以本質是不同的。

在這裡我就不再贅述繼承的概念的東西,相信懂一點c++的程式設計師都會使用繼承,但是在這裡強調一下繼承的賦值相容規則

子類物件可以賦值給父類物件(切片:將子類物件中切割出父類大小的乙個物件賦值給父類物件(指標))

父類物件不可以複製給子類物件。

父類的指標/引用可以指向子類物件。

子類指標/物件不可以指向父類的物件。(除非強制型別轉換,但是這是不好的)。

賦值相容規則在虛擬繼承中會使用到,所以在這裡複習一下。

虛擬繼承主要指解決菱形繼承的二義性問題:

菱形繼承:多個子類繼承同乙個基類,最後又被乙個子類繼承。

從物件模型我們可以看見assistat的虛表(vtable),其實虛表有很多叫法:

vmtvftable

virtual call table

dispatch table

vtable

我們一般稱為vtable。虛表是c++利用runtime來實現多型的工具,也就是在執行時決定到底選用的是哪乙個虛表。所以,我們借助virtual關鍵字將函式**位址存入vtable來躲開靜態編譯期,當編譯器看到virtual關鍵字時,編譯器自動跳過。

我們來看乙個沒有使用虛函式的**:

#includeusing namespace std;

class person

protected:

string _name; // 姓名

};class student : public person

protected:

int _num; //學號

執行程式,輸出的是兩個買票,說明父類和子類都是呼叫的父類的void buytickets(),因為沒有使用virtual關鍵字修飾在靜態編譯期就確定了呼叫person的void buytickets()。

然後,我們在void buytickets()的前面加上vitral會怎樣呢:

class person

protected:

string _name; // 姓名

正如你看到的輸出是買票和買票-半價,這就說明多型已經成功的實現了,但是,為什麼呢?????

首先,我們得先理解一下幾點:

函式只要有virtual,我們就需要把它新增鍵入vtable。

每個類都有自己的虛表。

虛表的位置一般存放在模組的常量段中,從始至終都只有乙份。

虛表裡有虛函式指標,指向本類中帶有virtual的函式。

虛函式指標的大小是4個位元組,就本例來說虛表的大小就是4個位元組,因為只有乙個虛函式:

我們可以看到雖然student繼承了person但是,student任然有自己的虛表,並且student重寫了virtual void buytickets()。這就是原因。

以下是覆蓋的規則:

C 虛函式和虛表

對c 了解的人都應該知道虛函式 virtual function 是通過一張虛函式表 virtual table 來實現的。簡稱為v table。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了繼承 覆蓋的問題,保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了這個例項的...

C 虛函式 虛表和純虛函式

定義 用virtual修飾的成員函式稱為虛函式 重寫 覆蓋 當在子類中定義了乙個與父類完全相同的虛函式時,則稱這個子類的函式重寫 或覆蓋 了父類的函式 例 includeusing namespace std class person virtual void h1 int b class deri...

虛函式 虛指標和虛表

關於虛函式的背景知識 用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。存在虛函式的類都有乙個一維的虛函式表叫做虛表。類的物件有乙個指向虛表開始的虛指標。虛表是和類對應的,虛表指標是和物件對應的。多型性是乙個介面多種實現,是物件導向的核心。分為類的多型性和函式的多型性。多型用虛函...