網(wǎng)站首頁 編程語言 正文
基類實(shí)現(xiàn)
我們先實(shí)現(xiàn)一個(gè)基類
class BaseTest
{
private:
virtual void display() { cout << "Base display" << endl; }
void say() { cout << "Base say()" << endl; }
public:
virtual void func() { cout << "Base func()" << endl; }
void exec()
{
display();
say();
}
void f1(string a) { cout << "Base f1(string)" << endl; }
void f1(int a) { cout << "Base f1(int)" << endl; }
void exec2()
{
display();
say();
}
};
BaseTest類中我們實(shí)現(xiàn)了一個(gè)虛函數(shù)display和 func。
BaseTest類內(nèi)部重載了f1函數(shù),實(shí)現(xiàn)了兩個(gè)版本,一個(gè)參數(shù)為string一個(gè)參數(shù)為int。
同一個(gè)類中的多個(gè)同名函數(shù)叫做重載。
實(shí)現(xiàn)了普通函數(shù)say,exec以及exec2函數(shù)。exec和exec2函數(shù)內(nèi)部調(diào)用了display和say函數(shù)。
子類實(shí)現(xiàn)
子類DeriveA繼承了基類
class DeriveA : public BaseTest
{
public:
void display() { cout << "DeriveA display()" << endl; }
void f1(int a, int b) { cout << "DeriveA f1(int,int)" << endl; }
void say() { cout << "DeriveA say()" << endl; }
virtual void func() { cout << "DeriveA func()" << endl; }
void use_base_f1(int a, int b)
{
BaseTest::f1(2);
BaseTest::f1("test");
cout << "DeriveA f1(int, int)" << endl;
}
void exec2()
{
display();
say();
}
};
子類DeriveA 子類重新實(shí)現(xiàn)了display和func函數(shù),子類重新實(shí)現(xiàn)父類的虛函數(shù),叫做重寫。
同樣子類重新實(shí)現(xiàn)了f1和say函數(shù),由于父類有f1和say,所以子類重新實(shí)現(xiàn)覆蓋了父類的函數(shù),
這種普通函數(shù)被子類重寫導(dǎo)致父類的函數(shù)被隱藏了,叫做覆蓋。
函數(shù)調(diào)用
接下來我們通過函數(shù)調(diào)用,看一下覆蓋,重載和重寫的區(qū)別
void derive_base_test1()
{
DeriveA a;
BaseTest *b = &a;
shared_ptr<BaseTest> c = make_shared<BaseTest>();
//輸出DeriveA func()
b->func();
//輸出DeriveA func()
a.func();
//輸出Base f1(string)
b->f1("abc");
//輸出Base f1(int)
b->f1(3);
//輸出DeriveA f1(int,int)
a.f1(3, 5);
a.use_base_f1(2, 4);
cout << "========================" << endl;
//輸出DeriveA display()
//輸出Base say()
b->exec();
//輸出DeriveA display()
//輸出Base say()
a.exec();
//輸出Base display
//輸出Base say()
c->exec();
cout << "======================== \n"
<< endl;
//輸出 DeriveA display()
//輸出 Base say()
b->exec2();
//輸出 DeriveA display()
//輸出 DeriveA say()
a.exec2();
//輸出 Base display
//輸出 Base say()
c->exec2();
}
代碼里我們生成了一個(gè)DeriveA的實(shí)例a, 并將該實(shí)例返回給基類BaseTest的指針b,所以:
1 ? b->func();會根據(jù)多態(tài)的效果調(diào)用子類DeriveA的func函數(shù)
2 ? a.func() 因?yàn)閍是一個(gè)對象,所以調(diào)用子類DeriveA的func函數(shù)
3 ? b->f1(“abc”) 調(diào)用基類BaseTest的f1,因?yàn)閒1是一個(gè)普通函數(shù)
4 ? a.f1(3, 5) 調(diào)用DeriveA的f1,因?yàn)閍是一個(gè)普通對象。
5 ? 當(dāng)我們想在子類里調(diào)用基類的f1函數(shù),可以通過基類作用域加函數(shù)名的方式,比如例子中的
a.use_base_f1就在函數(shù)內(nèi)部通過BaseTest::f1調(diào)用了基類函數(shù)f1
6 ? b->exec,首先b是一個(gè)指針且exec為普通函數(shù)只在基類實(shí)現(xiàn)了,所以調(diào)用基類的exec,
但是exec內(nèi)部調(diào)用了虛函數(shù)display,此時(shí)觸發(fā)多態(tài)機(jī)制調(diào)用DeriveA的display函數(shù),因?yàn)閎是一個(gè)指向子類DeriveA對象的基類BaseTest指針,exec內(nèi)部調(diào)用了普通函數(shù)display,因?yàn)閐isplay不是虛函數(shù),所以調(diào)用BaseTest的display函數(shù)
7 ? a.exec(); a是一個(gè)DeriveA對象,DeriveA自己沒有實(shí)現(xiàn)exec函數(shù),所以調(diào)用基類BaseTest的exec函數(shù),exec內(nèi)部調(diào)用display虛函數(shù)時(shí)由于DeriveA重寫了display函數(shù),所以調(diào)用DeriveA的display函數(shù),exec內(nèi)部調(diào)用say函數(shù)時(shí)由于say是普通函數(shù),所以此時(shí)調(diào)用的是BaseTest的say函數(shù)。
8 ? c->exec(); 因?yàn)閏為BaseTest類型,所以調(diào)用的就是BaseTest的exec,內(nèi)部執(zhí)行的也是BaseTest的display和say。
9 ?b->exec2(); 因?yàn)閎是一個(gè)子類BaseTest的指針,所以調(diào)用BaseTest的exec2函數(shù),exec2內(nèi)部調(diào)用display時(shí)觸發(fā)多態(tài)機(jī)制調(diào)用DeriveA的display,調(diào)用say時(shí)因?yàn)閟ay是普通函數(shù),所以調(diào)用BaseTest的say函數(shù)。
10 ? a.exec2(); 因?yàn)閍是DeriveA類對象,且DeriveA實(shí)現(xiàn)了exec2,所以a調(diào)用DeriveA的exec2,這樣exec2內(nèi)部調(diào)用的都是DeriveA的say和display
11 ? c->exec2(); c為BaseTest類對象,所以調(diào)用BaseTest類的exec2以及display和say函數(shù)。
總結(jié)
考察一個(gè)函數(shù)是被子類還是基類調(diào)用時(shí)應(yīng)該分以下幾種情況
1 ?該函數(shù)是虛函數(shù)并且被子類重寫,如果是基類指針指向子類對象,調(diào)用該函數(shù)則引發(fā)多態(tài)機(jī)制,調(diào)用子類的虛函數(shù)
2 ? 如果該函數(shù)時(shí)虛函數(shù)并且沒有被重寫,那么無論調(diào)用的對象是基類指針還是子類對象,還是基類對象,
還是子類指針都是調(diào)用基類的這個(gè)虛函數(shù)
3 ? 如果該函數(shù)不是虛函數(shù),如果該函數(shù)被子類覆蓋(子類重新定義了同名函數(shù)),那么調(diào)用規(guī)則就是子類調(diào)用子類的該函數(shù),
基類調(diào)用該基類的函數(shù)。
4 ? 如果該函數(shù)不是虛函數(shù),并且子類沒有定義同名函數(shù)(沒有覆蓋基類同名函數(shù)),那么無論是子類還是基類的指針或者對象,
統(tǒng)一調(diào)用的是基類的函數(shù)。
5 ? 如果第4點(diǎn)里基類的函數(shù)(沒有被子類覆蓋),但是內(nèi)部調(diào)用了基類的虛函數(shù),并且該虛函數(shù)被子類重寫,這時(shí)內(nèi)部這個(gè)虛函數(shù)調(diào)用規(guī)則
就要看調(diào)用對象的實(shí)際類型,符合1的調(diào)用標(biāo)準(zhǔn),多態(tài)就走子類,不是多態(tài)就走基類(此時(shí)符合2標(biāo)準(zhǔn))
6 ?如果第3點(diǎn)里基類的函數(shù)(被子類覆蓋),但是內(nèi)部調(diào)用了基類的虛函數(shù),并且該虛函數(shù)被子類重寫,這時(shí)內(nèi)部這個(gè)虛函數(shù)調(diào)用規(guī)則
就要看調(diào)用對象的實(shí)際類型,符合1的調(diào)用標(biāo)準(zhǔn),多態(tài)就走子類,不是多態(tài)就走基類(此時(shí)符合2標(biāo)準(zhǔn))
資源鏈接
本文模擬實(shí)現(xiàn)了vector的功能。
視頻鏈接
源碼鏈接?
原文鏈接:https://blog.csdn.net/secondtonone1/article/details/126046408
相關(guān)推薦
- 2022-06-29 python人工智能tensorflow構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)CNN_python
- 2023-03-15 Pandas中字符串和時(shí)間轉(zhuǎn)換與格式化的實(shí)現(xiàn)_python
- 2022-06-11 Python?tkinter庫圖形繪制例子分享_python
- 2022-03-20 關(guān)于Rancher部署并導(dǎo)入K8S集群的問題_云其它
- 2022-11-22 ubuntu20.04中vscode使用ROS的詳細(xì)方法_C 語言
- 2022-07-13 Python內(nèi)建類型float源碼學(xué)習(xí)_python
- 2022-07-09 python處理excel文件之xlsxwriter?模塊_python
- 2022-03-30 詳解Python的條件語句_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支