概念
多態(tài)在代碼中指的就是“一個接口,多種實現(xiàn)”(相同的調(diào)用方法有不同的實現(xiàn)方式),屬于面向?qū)ο缶幊痰暮诵母拍睢V義的多態(tài)包括靜態(tài)多態(tài)和動態(tài)多態(tài),其中靜態(tài)多態(tài)指的是編譯時就可以確認(rèn)使用的接口,動態(tài)多態(tài)指的是運行時才能確定具體引用的接口。
靜態(tài)多態(tài)和動態(tài)多態(tài)本質(zhì)上的區(qū)別在于什么時候(編譯期間or運行期間)將函數(shù)實現(xiàn)與函數(shù)調(diào)用關(guān)聯(lián)起來。靜態(tài)多態(tài)在編譯期間就可以確定函數(shù)的調(diào)用地址并產(chǎn)生對應(yīng)代碼,動態(tài)多態(tài)在運行時才能確定函數(shù)的調(diào)用地址。
實例
1. 靜態(tài)多態(tài)
靜態(tài)多態(tài)往往通過函數(shù)重載和泛型編程(模板)實現(xiàn):
#include <iostream>
// int型的加法函數(shù)
int add(int a, int b) {
return a + b;
}
// double型的加法函數(shù)
double add(double a, double b) {
return a + b;
}
// 函數(shù)模板的加法函數(shù)
template <typename T> T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(1, 1) << std::endl; // 調(diào)用int型的加法函數(shù)
std::cout << add(1.2, 3.4) << std::endl; // 調(diào)用double型的加法函數(shù)
std::cout << add<char>('A', ' ') << std::endl; // 調(diào)用函數(shù)模板的加法函數(shù), 輸出小寫字母a
}
編譯輸出:
$g++ -o main main.cpp
$./main
2
4.6
a
2. 動態(tài)多態(tài)
動態(tài)多態(tài)最常見的方法就是使用基類的指針(或引用)調(diào)用一個虛函數(shù):
#include <iostream>
// 基類
class Base {
public:
virtual std::string foo() {
return "Base::foo()";
}
};
// 派生類
class Derived : public Base {
public:
std::string foo() override {
return "Derived::foo()";
}
};
int main() {
// pb靜態(tài)類型為Base*, 動態(tài)類型Derived*
Base *pb = new Derived;
std::cout << pb->foo() << std::endl;
// rb靜態(tài)類型為Base&, 動態(tài)類型為Derived&
Base &rb = *(new Derived);
std::cout << rb.foo() << std::endl;
}
編譯輸出:
# override使用到了C++11新特性, 加上編譯參數(shù)-std=c++11
$g++ -o main -std=c++11 main.cpp
$./main
Derived::foo()
Derived::foo()
使用多態(tài)的原因
面向?qū)ο缶幊讨蟹庋b可以使得代碼模塊化,繼承可以擴(kuò)展已存在的代碼,這兩者的本質(zhì)都是為了代碼重用。而多態(tài)的目的在于接口重用。靜態(tài)多態(tài)可以根據(jù)傳入不同的參數(shù)(不同參數(shù)個數(shù)或者不同參數(shù)類型)調(diào)用不同的實現(xiàn),動態(tài)多態(tài)可以用相同的代碼處理基類和派生類對象,運行時再根據(jù)基類的引用(或指針)所綁定對象的真實類型來調(diào)用不同的實現(xiàn)。
和封裝繼承一樣,多態(tài)不僅可以改善代碼的組織結(jié)構(gòu)和可讀性,還可以讓程序更加具有可擴(kuò)展性。
Reference
[1] https://zhuanlan.zhihu.com/p/37340242
[2] https://blog.csdn.net/qq_43461641/article/details/100139924
[3] https://blog.csdn.net/zcxwww/article/details/51303928
[4] https://www.runoob.com/cplusplus/cpp-polymorphism.html
[5] https://blog.csdn.net/qq_37934101/article/details/81365449