日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数

發(fā)布時(shí)間:2023/11/27 生活经验 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們都知道面向?qū)ο缶幊痰娜筇卣魇?span style="color:#fe2c24;">封裝、繼承、多態(tài),今天我們就來(lái)說(shuō)一下其中之一的多態(tài)。

概念:

多態(tài):

多態(tài)字面意思就是多種形態(tài),C++ 多態(tài)意味著調(diào)用成員函數(shù)時(shí),會(huì)根據(jù)調(diào)用函數(shù)的對(duì)象的類型來(lái)執(zhí)行不同的函數(shù)。(取自菜鳥教程)

多態(tài)分類:

多態(tài)分為編譯時(shí)多態(tài)(早期綁定)和運(yùn)行時(shí)多態(tài)(后期綁定)

編譯時(shí)多態(tài)(早期綁定=靜態(tài)聯(lián)編)

概念:

? ? ? ? 通過(guò)函數(shù)重載和運(yùn)算符重載來(lái)實(shí)現(xiàn)。

特點(diǎn):

? ? ? ? 在編譯時(shí)我們就已經(jīng)知道調(diào)用的是哪些個(gè)函數(shù)

看下面的代碼:

int Max(int a, int b) { return a > b ? a : b }
char Max(char a, char b) { return a > b ? a : b }
double Max(double a, double b) { return a > b ? a : b }int main()
{int x = Max(12, 23);char ch = Max('a', 'b');double de = Max(12.23, 34.45);return 0;
}

上述代碼我們通過(guò)重載函數(shù)Max來(lái)實(shí)現(xiàn)早期綁定,也就是在我們編譯的時(shí)候通過(guò)函數(shù)重載的機(jī)制就已經(jīng)知道調(diào)用的是哪個(gè)函數(shù),比如Max(12,23)參數(shù)為int整型類型的參數(shù),所以我們就知道調(diào)用的是第一個(gè)int Max()這個(gè)函數(shù)。

運(yùn)行時(shí)多態(tài)(動(dòng)態(tài)綁定=動(dòng)態(tài)聯(lián)編)

概念:

????????運(yùn)行時(shí)的多態(tài)性是指在程序執(zhí)行前,無(wú)法根據(jù)函數(shù)名和參數(shù)來(lái)確定該調(diào)用哪一個(gè)函數(shù),必須在程序執(zhí)行過(guò)程中,根據(jù)執(zhí)行的具體情況來(lái)動(dòng)態(tài)地確定。它是通過(guò)類繼承關(guān)系public和虛函數(shù)來(lái)實(shí)現(xiàn)的。

特點(diǎn):
? ? ? ? 同一個(gè)方法在不同的對(duì)象身上體現(xiàn)出來(lái)不同的代碼形式,但是我們有統(tǒng)一的接口,例如下面代碼中的fun函數(shù)這個(gè)方法,在基類中和派生類中體現(xiàn)出來(lái)的方法不一樣!!!

? ? ? ? 就是說(shuō)運(yùn)行時(shí)多態(tài)是通過(guò)虛函數(shù)來(lái)實(shí)現(xiàn)的。虛函數(shù)在我上一篇說(shuō)過(guò):【C++】虛函數(shù)_神廚小福貴!的博客-CSDN博客虛函數(shù)是構(gòu)成C++多態(tài)的重要一步,今天來(lái)說(shuō)一下虛函數(shù)!虛函數(shù):在基類(或父類)中,使用virtual關(guān)鍵字對(duì)函數(shù)進(jìn)行聲明為并在一個(gè)或多個(gè)派生類(子類)中被重新定義的成員函數(shù),通過(guò)指向派生類的基類指針或引用,訪問(wèn)派生類中同名覆蓋成員函數(shù)。它的用法是這樣的:virtual + 函數(shù)返回類型 + 函數(shù)名 +(參數(shù)表) {函數(shù)體}首先我們要知道為什么要有虛函數(shù)這個(gè)東西?我來(lái)看下下面這兩段代碼的結(jié)果再來(lái)說(shuō)結(jié)果:class A{public:void fun(){couthttps://blog.csdn.net/qq_45829112/article/details/123460960?spm=1001.2014.3001.5502

下面我那代碼來(lái)實(shí)現(xiàn)一下動(dòng)態(tài)綁定:

class A
{
public:virtual void fun(){}
};class B :public A
{
public:virtual void fun(){cout << "class B::fun()" << endl;}
};class C :public A
{
public:virtual void fun(){cout << "class C::fun()" << endl;}
};void pun(A& a)
{a.fun();
}int main()
{B b;C c;pun(b);pun(c);return 0;
}

類B、C都公有繼承類A,然后創(chuàng)建bc對(duì)象,分別調(diào)用函數(shù)pun,當(dāng)傳入?yún)?shù)為class B參數(shù)時(shí) 調(diào)用B中的婦女函數(shù),傳參為class C時(shí),調(diào)用類C中的fun函數(shù)!、

上述代碼解析如下圖所示:

運(yùn)行結(jié)果:

這就是簡(jiǎn)單的運(yùn)行時(shí)的多態(tài),相同的方法在不同的 不同對(duì)象下進(jìn)行調(diào)用時(shí),產(chǎn)生的結(jié)果也不盡相同,這也就是簡(jiǎn)單的運(yùn)行時(shí)的多態(tài)!!!

抽象類(純虛函數(shù))

概念:

? ? ? ? 含有純虛函數(shù)的類稱為抽象類。純虛函數(shù)沒(méi)有實(shí)現(xiàn)部分,不能產(chǎn)生對(duì)象。

? ? ? ? 簡(jiǎn)單來(lái)說(shuō)就是抽象類(有純虛函數(shù)的類)不能定義對(duì)象!!!

????????virtual? 類型? 函數(shù)名(參數(shù)列表)= 0? 如下所示:

virtual void fun() { } = 0;

下面來(lái)說(shuō)下純虛函數(shù)的特點(diǎn):

? ? ? ??抽象類只能作為基類來(lái)使用,其純虛函數(shù)的實(shí)現(xiàn)由派生類給出。如果派生類沒(méi)有重新定義純虛函數(shù),而派生類只是繼承基類的純虛函數(shù),則這個(gè)派生類仍然還是一個(gè)抽象類。如果派生類中給出了基類純虛函數(shù)的實(shí)現(xiàn),則該派生類就不再是抽象類了,它是一個(gè)可以建立對(duì)象的具體類了。
?

? ? ? ? 可能會(huì)有些抽象,舉個(gè)簡(jiǎn)單例子就是說(shuō),你說(shuō)你要去混社會(huì)去了,但是有社會(huì)這個(gè)實(shí)體這個(gè)對(duì)象嘛,顯然是沒(méi)有的,我們只能在社會(huì)上做某些事情,而沒(méi)有社會(huì)這個(gè)實(shí)體,大致就這么個(gè)意思!!!

那么純虛函數(shù)以及這個(gè)抽象類有什么作用呢???

class A
{
public:virtual void fun() {} = 0; //純虛函數(shù)
};class B :public A
{
public:virtual void fun()   //必須要進(jìn)行重寫,否則class B也是一個(gè)抽象類,不可以定義對(duì)象{cout << "class B::fun()" << endl;}
};class C :public A
{
public:virtual void fun()  //必須要進(jìn)行重寫,否則class C也是一個(gè)抽象類,不可以定義對(duì)象{cout << "class C::fun()" << endl;}
};

? ? ? ? 抽象類一般作為接口來(lái)使用,真正的實(shí)現(xiàn)都是在其派生類中進(jìn)行實(shí)現(xiàn),如上述代碼中所示,在基類A中的fun啥也不干,僅僅搞個(gè)純虛函數(shù),真正的實(shí)現(xiàn)都是在其派生類class B和class C中來(lái)進(jìn)行實(shí)現(xiàn)的。

析構(gòu)函數(shù)為什么聲明為虛函數(shù)???

class A
{
public:A(int x = 10){cout << "A構(gòu)造函數(shù)運(yùn)行" << endl;}virtual void fun(){}~A(){cout << "~A運(yùn)行" << endl;}
};class B :public A
{
public:B(int x = 10){cout << "B構(gòu)造函數(shù)運(yùn)行" << endl;}~B(){cout << "~B運(yùn)行" << endl;}virtual void fun(){cout << "class B::fun()" << endl;}
};int main()
{A* op = new B(10);op->fun();delete op;op = nullptr;return 0;
}

觀察上述代碼,父類指針指向派生類對(duì)象,完成執(zhí)行fun函數(shù)之后,我們對(duì)op指針?biāo)赶蛸Y源進(jìn)行釋放以及置空,運(yùn)行結(jié)果:

?為啥上面我們構(gòu)造了兩次,最后釋放卻只釋放了一次呢?

? ? ? ? 原因是我們op是基類指針,指向派生類的對(duì)象,構(gòu)造class B的無(wú)名對(duì)象的時(shí)候,先構(gòu)造A的隱藏父對(duì)象,再構(gòu)造B對(duì)象,但是我們釋放的時(shí)候因?yàn)槭腔愔羔?#xff0c;所以只能找到基類的析構(gòu)函數(shù),所以我們派生類的對(duì)象就沒(méi)有進(jìn)行釋放,可能會(huì)造成內(nèi)存泄漏!!!

怎么解決這個(gè)問(wèn)題呢?父類析構(gòu)函數(shù)加虛聲明virtual:

class A
{
public:A(int x = 10){cout << "A構(gòu)造函數(shù)運(yùn)行" << endl;}virtual void fun(){}virtual ~A()   //構(gòu)造函數(shù)加virtual聲明{cout << "~A運(yùn)行" << endl;}
};class B :public A
{
public:B(int x = 10){cout << "B構(gòu)造函數(shù)運(yùn)行" << endl;}~B(){cout << "~B運(yùn)行" << endl;}virtual void fun(){cout << "class B::fun()" << endl;}
};int main()
{A* op = new B(10);op->fun();delete op;op = nullptr;return 0;
}

至于派生類的析構(gòu)函數(shù),我們可以加也可以不加,因?yàn)槿绻覀兣缮愡€有派生類的話,就得加virtual聲明,下面我們來(lái)看運(yùn)行結(jié)果:

我們?cè)诨愔袑⑽鰳?gòu)函數(shù)聲明為virtual虛函數(shù),派生類相當(dāng)于繼承了虛函數(shù)這個(gè)特性,所以析構(gòu)的時(shí)候,就可以通過(guò)虛表指針來(lái)找到派生類中的虛函數(shù)來(lái)對(duì)派生類對(duì)象進(jìn)行析構(gòu)!!!

總結(jié)

以上是生活随笔為你收集整理的【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。