網站首頁 編程語言 正文
闡述虛函數作用和原理、純虛函數和虛函數的區別。
一、虛函數
首先來看下面這一段代碼,首先創建兩個類,一個是Dog,另一個是Cat,他們有一個共同的屬性:Run。在定義中每個動物都需要創建一個類,比較繁瑣,所以在下面的例子中,我們可以把他們簡化。
#include <iostream>
using namespace std;
class Dog{
public:
void Run(){
cout<<"Dog->Run"<<endl;
}
};
class Cat{
public:
void Run(){
cout<<"Cat->Run"<<endl;
}
};
int main()
{
Dog d;
d.Run();
Cat c;
c.Run();
return 0;
}
這里使用多態和虛函數,而Animal提供統一的接口,供子類使用,雖然代碼繁瑣,但提高了整個工程的可擴展性和靈活性。
在普通函數前加上關鍵字 virtual 構成虛函數,子類需要重寫父類的虛函數,這樣在調用的時候,會覆蓋掉父類的虛函數 Run,去執行子類的Run。
#include <iostream>
using namespace std;
class Animal{
public:
virtual void Run(){
cout<<"Animal->Run"<<endl;
}
};
class Dog :public Animal{
public:
void Run(){
cout<<"Dog->Run"<<endl;
}
};
class Cat:public Animal{
public:
void Run(){
cout<<"Cat->Run"<<endl;
}
};
int main()
{
Animal *ani;
ani = new Dog;
ani->Run();
delete ani;
ani = new Cat;
ani->Run();
delete ani;
return 0;
}
結果如下:
所以在這里只需要修改ani的指向就可以實現不同方法。如果不存在虛函數,把Animal類的關鍵詞virtual去掉會怎么樣呢,顯然,他們會默認實現父類Run的方法。
class Animal{
public:
void Run(){
cout<<"Animal->Run"<<endl;
}
};
所以引入虛函數是為了實現動態多態,指向不同的子類來實現不同的方法。
二、虛函數與純虛函數的區別
因為父類的函數可以不做任何操作,所以這里可以直接等于0;實現純虛函數。
//虛函數
class Animal{
public:
virtual void Run(){
cout<<"Animal->Run"<<endl;
}
};
//純虛函數
class Animal{
public:
virtual void Run()=0;
};
虛函數與純虛函數的區別:
純虛函數只是一個接口,只能供子類去重寫實現方法。而虛函數在里面也可以去實現父類的功能。只需要指向父類的方法即可。
總結:虛函數在子類里面也可以不進行重寫,但純虛函數必須在子類去實現,如果把子類中的Run方法去掉,只留下父類中的純虛函數,那么編譯器會報錯,這里大家可以試試。
三、動態多態
Animal內部的結構是什么樣呢?這里有一個虛函數指針(vfptr)和虛函數表(vftable)。 指針(vfptr)指向虛函數表,在虛函數表(vftable)內記錄著虛函數的地址,即Run函數的地址。
當子類的Dog去繼承父類后,父類的虛函數表相應的也繼承下來,子類也會保存一份和父類相同的。
注意!這時候如果發生重寫,即子類重寫了父類的虛函數,則子類的虛函數表會覆蓋父類繼承下來的虛函數表。但父類的虛函數表不會發生改變。
當父類的指針或者引用指向子類的對象時,就發生了多態。
下面的代碼中是指向了Dog,所以會去Dog的虛函數表中找到相應的函數,在運行階段發生了動態多態。
Animal *ani;
ani = new Dog;
ani->Run();
原文鏈接:https://blog.csdn.net/qq_53734051/article/details/126465524
相關推薦
- 2022-09-25 linux基礎入門1 vi/vim編輯器
- 2022-08-19 Python包中__init__.py文件的作用與用法實例詳解_python
- 2023-02-09 Golang實現Trie(前綴樹)的示例_Golang
- 2022-08-20 Python超詳細講解內存管理機制_python
- 2022-09-22 git-lfs 離線安裝
- 2022-12-29 React使用公共文件夾public問題_React
- 2022-04-15 詳解Python?prometheus_client使用方式_python
- 2022-05-23 如何使Python中的print()語句運行結果不換行_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支