【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数
我們都知道面向對象編程的三大特征是封裝、繼承、多態(tài),今天我們就來說一下其中之一的多態(tài)。
概念:
多態(tài):
多態(tài)字面意思就是多種形態(tài),C++ 多態(tài)意味著調用成員函數(shù)時,會根據(jù)調用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)。(取自菜鳥教程)
多態(tài)分類:
多態(tài)分為編譯時多態(tài)(早期綁定)和運行時多態(tài)(后期綁定)
編譯時多態(tài)(早期綁定=靜態(tài)聯(lián)編)
概念:
? ? ? ? 通過函數(shù)重載和運算符重載來實現(xiàn)。
特點:
? ? ? ? 在編譯時我們就已經知道調用的是哪些個函數(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;
}
上述代碼我們通過重載函數(shù)Max來實現(xiàn)早期綁定,也就是在我們編譯的時候通過函數(shù)重載的機制就已經知道調用的是哪個函數(shù),比如Max(12,23)參數(shù)為int整型類型的參數(shù),所以我們就知道調用的是第一個int Max()這個函數(shù)。
運行時多態(tài)(動態(tài)綁定=動態(tài)聯(lián)編)
概念:
????????運行時的多態(tài)性是指在程序執(zhí)行前,無法根據(jù)函數(shù)名和參數(shù)來確定該調用哪一個函數(shù),必須在程序執(zhí)行過程中,根據(jù)執(zhí)行的具體情況來動態(tài)地確定。它是通過類繼承關系public和虛函數(shù)來實現(xiàn)的。
特點:
? ? ? ? 同一個方法在不同的對象身上體現(xiàn)出來不同的代碼形式,但是我們有統(tǒng)一的接口,例如下面代碼中的fun函數(shù)這個方法,在基類中和派生類中體現(xiàn)出來的方法不一樣!!!
? ? ? ? 就是說運行時多態(tài)是通過虛函數(shù)來實現(xiàn)的。虛函數(shù)在我上一篇說過:【C++】虛函數(shù)_神廚小福貴!的博客-CSDN博客虛函數(shù)是構成C++多態(tài)的重要一步,今天來說一下虛函數(shù)!虛函數(shù):在基類(或父類)中,使用virtual關鍵字對函數(shù)進行聲明為并在一個或多個派生類(子類)中被重新定義的成員函數(shù),通過指向派生類的基類指針或引用,訪問派生類中同名覆蓋成員函數(shù)。它的用法是這樣的:virtual + 函數(shù)返回類型 + 函數(shù)名 +(參數(shù)表) {函數(shù)體}首先我們要知道為什么要有虛函數(shù)這個東西?我來看下下面這兩段代碼的結果再來說結果:class A{public:void fun(){couthttps://blog.csdn.net/qq_45829112/article/details/123460960?spm=1001.2014.3001.5502
下面我那代碼來實現(xiàn)一下動態(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對象,分別調用函數(shù)pun,當傳入參數(shù)為class B參數(shù)時 調用B中的婦女函數(shù),傳參為class C時,調用類C中的fun函數(shù)!、
上述代碼解析如下圖所示:
運行結果:
這就是簡單的運行時的多態(tài),相同的方法在不同的 不同對象下進行調用時,產生的結果也不盡相同,這也就是簡單的運行時的多態(tài)!!!
抽象類(純虛函數(shù))
概念:
? ? ? ? 含有純虛函數(shù)的類稱為抽象類。純虛函數(shù)沒有實現(xiàn)部分,不能產生對象。
? ? ? ? 簡單來說就是抽象類(有純虛函數(shù)的類)不能定義對象!!!
????????virtual? 類型? 函數(shù)名(參數(shù)列表)= 0? 如下所示:
virtual void fun() { } = 0;
下面來說下純虛函數(shù)的特點:
? ? ? ??抽象類只能作為基類來使用,其純虛函數(shù)的實現(xiàn)由派生類給出。如果派生類沒有重新定義純虛函數(shù),而派生類只是繼承基類的純虛函數(shù),則這個派生類仍然還是一個抽象類。如果派生類中給出了基類純虛函數(shù)的實現(xiàn),則該派生類就不再是抽象類了,它是一個可以建立對象的具體類了。
?
? ? ? ? 可能會有些抽象,舉個簡單例子就是說,你說你要去混社會去了,但是有社會這個實體這個對象嘛,顯然是沒有的,我們只能在社會上做某些事情,而沒有社會這個實體,大致就這么個意思!!!
那么純虛函數(shù)以及這個抽象類有什么作用呢???
class A
{
public:virtual void fun() {} = 0; //純虛函數(shù)
};class B :public A
{
public:virtual void fun() //必須要進行重寫,否則class B也是一個抽象類,不可以定義對象{cout << "class B::fun()" << endl;}
};class C :public A
{
public:virtual void fun() //必須要進行重寫,否則class C也是一個抽象類,不可以定義對象{cout << "class C::fun()" << endl;}
};
? ? ? ? 抽象類一般作為接口來使用,真正的實現(xiàn)都是在其派生類中進行實現(xiàn),如上述代碼中所示,在基類A中的fun啥也不干,僅僅搞個純虛函數(shù),真正的實現(xiàn)都是在其派生類class B和class C中來進行實現(xiàn)的。
析構函數(shù)為什么聲明為虛函數(shù)???
class A
{
public:A(int x = 10){cout << "A構造函數(shù)運行" << endl;}virtual void fun(){}~A(){cout << "~A運行" << endl;}
};class B :public A
{
public:B(int x = 10){cout << "B構造函數(shù)運行" << endl;}~B(){cout << "~B運行" << endl;}virtual void fun(){cout << "class B::fun()" << endl;}
};int main()
{A* op = new B(10);op->fun();delete op;op = nullptr;return 0;
}
觀察上述代碼,父類指針指向派生類對象,完成執(zhí)行fun函數(shù)之后,我們對op指針所指向資源進行釋放以及置空,運行結果:
?為啥上面我們構造了兩次,最后釋放卻只釋放了一次呢?
? ? ? ? 原因是我們op是基類指針,指向派生類的對象,構造class B的無名對象的時候,先構造A的隱藏父對象,再構造B對象,但是我們釋放的時候因為是基類指針,所以只能找到基類的析構函數(shù),所以我們派生類的對象就沒有進行釋放,可能會造成內存泄漏!!!
怎么解決這個問題呢?父類析構函數(shù)加虛聲明virtual:
class A
{
public:A(int x = 10){cout << "A構造函數(shù)運行" << endl;}virtual void fun(){}virtual ~A() //構造函數(shù)加virtual聲明{cout << "~A運行" << endl;}
};class B :public A
{
public:B(int x = 10){cout << "B構造函數(shù)運行" << endl;}~B(){cout << "~B運行" << endl;}virtual void fun(){cout << "class B::fun()" << endl;}
};int main()
{A* op = new B(10);op->fun();delete op;op = nullptr;return 0;
}
至于派生類的析構函數(shù),我們可以加也可以不加,因為如果我們派生類還有派生類的話,就得加virtual聲明,下面我們來看運行結果:
我們在基類中將析構函數(shù)聲明為virtual虛函數(shù),派生類相當于繼承了虛函數(shù)這個特性,所以析構的時候,就可以通過虛表指針來找到派生類中的虛函數(shù)來對派生類對象進行析構!!!
總結
以上是生活随笔為你收集整理的【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 光遇兔子头饰要多少钱?
- 下一篇: 万能的天涯,有人知道这双鞋的品牌么!!!