詳解C++ 多態(tài)的兩種形式(靜態(tài)、動(dòng)態(tài))
1.多態(tài)的概念與分類
多態(tài)(Polymorphisn)是面向?qū)ο蟪绦蛟O(shè)計(jì)(OOP)的一個(gè)重要特征。多態(tài)字面意思為多種狀態(tài)。在面向?qū)ο笳Z言中,一個(gè)接口,多種實(shí)現(xiàn)即為多態(tài)。C++中的多態(tài)性具體體現(xiàn)在編譯和運(yùn)行兩個(gè)階段。編譯時(shí)多態(tài)是靜態(tài)多態(tài),在編譯時(shí)就可以確定使用的接口。運(yùn)行時(shí)多態(tài)是動(dòng)態(tài)多態(tài),具體引用的接口在運(yùn)行時(shí)才能確定。

靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)的區(qū)別其實(shí)只是在什么時(shí)候?qū)⒑瘮?shù)實(shí)現(xiàn)和函數(shù)調(diào)用關(guān)聯(lián)起來,是在編譯時(shí)期還是運(yùn)行時(shí)期,即函數(shù)地址是早綁定還是晚綁定的。靜態(tài)多態(tài)是指在編譯期間就可以確定函數(shù)的調(diào)用地址,并生產(chǎn)代碼,這就是靜態(tài)的,也就是說地址是早綁定。靜態(tài)多態(tài)往往也被叫做靜態(tài)聯(lián)編。 動(dòng)態(tài)多態(tài)則是指函數(shù)調(diào)用的地址不能在編譯器期間確定,需要在運(yùn)行時(shí)確定,屬于晚綁定,動(dòng)態(tài)多態(tài)往往也被叫做動(dòng)態(tài)聯(lián)編。
2.多態(tài)的作用
為何要使用多態(tài)呢?封裝可以使得代碼模塊化,繼承可以擴(kuò)展已存在的代碼,他們的目的都是為了代碼重用。而多態(tài)的目的則是為了接口重用。靜態(tài)多態(tài),將同一個(gè)接口進(jìn)行不同的實(shí)現(xiàn),根據(jù)傳入不同的參數(shù)(個(gè)數(shù)或類型不同)調(diào)用不同的實(shí)現(xiàn)。動(dòng)態(tài)多態(tài),則不論傳遞過來的哪個(gè)類的對(duì)象,函數(shù)都能夠通過同一個(gè)接口調(diào)用到各自對(duì)象實(shí)現(xiàn)的方法。
3.靜態(tài)多態(tài)
靜態(tài)多態(tài)往往通過函數(shù)重載和模版(泛型編程)來實(shí)現(xiàn),具體可見下面代碼:
#include <iostream>
using namespace std;
//兩個(gè)函數(shù)構(gòu)成重載
int add(int a, int b)
{
cout<<"in add_int_int()"<<endl;
return a + b;
}
double add(double a, double b)
{
cout<<"in add_double_doube()"<<endl;
return a + b;
}
//函數(shù)模板(泛型編程)
template <typename T>
T add(T a, T b)
{
cout<<"in func tempalte"<<endl;
return a + b;
}
int main()
{
cout<<add(1,1)<<endl; //調(diào)用int add(int a, int b)
cout<<add(1.1,1.1)<<endl; //調(diào)用double add(double a, double b)
cout<<add<char>('A',' ')<<endl; //調(diào)用模板函數(shù),輸出小寫字母a
}
程序輸出結(jié)果:
in add_int_int()
2
in add_double_doube()
2.2
in func tempalte
a
4.動(dòng)態(tài)多態(tài)
動(dòng)態(tài)多態(tài)最常見的用法就是聲明基類的指針,利用該指針指向任意一個(gè)子類對(duì)象,調(diào)用相應(yīng)的虛函數(shù),可以根據(jù)指向的子類的不同而調(diào)用不同的方法。如果沒有使用虛函數(shù),即沒有利用C++多態(tài)性,則利用基類指針調(diào)用相應(yīng)函數(shù)的時(shí)候,將總被限制在基類函數(shù)本身,而無法調(diào)用到子類中被重寫過的函數(shù)。因?yàn)闆]有多態(tài)性,函數(shù)調(diào)用的地址將是一定的,而固定的地址將始終調(diào)用同一個(gè)函數(shù),這就無法“實(shí)現(xiàn)一個(gè)接口,多種實(shí)現(xiàn)”的目的了。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void func()
{
cout << "Base::fun()" << endl;
}
};
class Derived : public Base
{
public:
virtual void func()
{
cout << "Derived::fun()" << endl;
}
};
int main()
{
Base* b=new Derived; //使用基類指針指向派生類對(duì)象
b->func(); //動(dòng)態(tài)綁定派生類成員函數(shù)func
Base& rb=*(new Derived); //也可以使用引用指向派生類對(duì)象
rb.func();
}
程序輸出結(jié)果:
Derived::fun()
Derived::fun()
通過上面的例子可以看出,在使用基類指針或引用指向子類對(duì)象時(shí),調(diào)用的函數(shù)是子類中重寫的函數(shù),這樣就實(shí)現(xiàn)了運(yùn)行時(shí)函數(shù)地址的動(dòng)態(tài)綁定,即動(dòng)態(tài)聯(lián)編。動(dòng)態(tài)多態(tài)是通過“繼承+虛函數(shù)”來實(shí)現(xiàn)的,只有在程序運(yùn)行期間(非編譯期)才能判斷所引用對(duì)象的實(shí)際類型,根據(jù)其實(shí)際類型調(diào)用相應(yīng)的方法。具體格式就是使用virtual關(guān)鍵字修飾類的成員函數(shù)時(shí),指明該函數(shù)為虛函數(shù),并且派生類需要重新實(shí)現(xiàn)該成員函數(shù),編譯器將實(shí)現(xiàn)動(dòng)態(tài)綁定。
以上就是詳解C++ 多態(tài)的兩種形式(靜態(tài)、動(dòng)態(tài))的詳細(xì)內(nèi)容,更多關(guān)于C++ 靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Qt使用SQLite數(shù)據(jù)庫(kù)存儲(chǔ)管理圖片文件
這篇文章主要為大家詳細(xì)介紹了Qt如何使用SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)存儲(chǔ)管理圖片文件的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04
C語言庫(kù)函數(shù)qsort及bsearch快速排序算法使用解析
這篇文章主要為大家介紹了C語言庫(kù)函數(shù)qsort及bsearch快速排序算法的使用示例解析2022-02-02
C++開源庫(kù)nlohmann/json的介紹和使用詳解
nlohmann/json?是一個(gè)C++實(shí)現(xiàn)的JSON解析器,使用非常方便直觀,這篇文章主要為大家詳細(xì)介紹了nlohmann/json的簡(jiǎn)介和使用,需要的可以參考下2023-12-12
C語言實(shí)現(xiàn)九大排序算法的實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于C語言實(shí)現(xiàn)九大排序算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
C語言從猜數(shù)字游戲中理解數(shù)據(jù)結(jié)構(gòu)
猜數(shù)字是興起于英國(guó)的益智類小游戲,起源于20世紀(jì)中期,一般由兩個(gè)人或多人玩,也可以由一個(gè)人和電腦玩。游戲規(guī)則為一方出數(shù)字,一方猜,今天我們來用這個(gè)游戲案例理解數(shù)據(jù)結(jié)構(gòu)2022-04-04

