[C++面試]多態

概念

多態在代碼中指的就是“一個接口,多種實現”(相同的調用方法有不同的實現方式),屬於面向對象編程的核心概念。廣義的多態包括靜態多態和動態多態,其中靜態多態指的是編譯時就可以確認使用的接口,動態多態指的是運行時才能確定具體引用的接口。

靜態多態和動態多態本質上的區別在於什麼時候(編譯期間or運行期間)將函數實現與函數調用關聯起來。靜態多態在編譯期間就可以確定函數的調用地址併產生對應代碼,動態多態在運行時才能確定函數的調用地址。

實例

1. 靜態多態

靜態多態往往通過函數重載和泛型編程(模板)實現:

#include <iostream>

// int型的加法函數
int add(int a, int b) {
    return a + b;
}

// double型的加法函數
double add(double a, double b) {
    return a + b;
}

// 函數模板的加法函數
template <typename T> T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add(1, 1) << std::endl;            // 調用int型的加法函數
    std::cout << add(1.2, 3.4) << std::endl;        // 調用double型的加法函數
    std::cout << add<char>('A', ' ') << std::endl;  // 調用函數模板的加法函數, 輸出小寫字母a
}

編譯輸出:

$g++ -o main main.cpp
$./main 
2
4.6
a

2. 動態多態

動態多態最常見的方法就是使用基類的指針(或引用)調用一個虛函數:

#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靜態類型爲Base*, 動態類型Derived*
    Base *pb = new Derived;
    std::cout << pb->foo() << std::endl;

    // rb靜態類型爲Base&, 動態類型爲Derived&
    Base &rb = *(new Derived);
    std::cout << rb.foo() << std::endl;
}

編譯輸出:

# override使用到了C++11新特性, 加上編譯參數-std=c++11
$g++ -o main -std=c++11 main.cpp
$./main 
Derived::foo()
Derived::foo()

使用多態的原因

面向對象編程中封裝可以使得代碼模塊化,繼承可以擴展已存在的代碼,這兩者的本質都是爲了代碼重用。而多態的目的在於接口重用。靜態多態可以根據傳入不同的參數(不同參數個數或者不同參數類型)調用不同的實現,動態多態可以用相同的代碼處理基類和派生類對象,運行時再根據基類的引用(或指針)所綁定對象的真實類型來調用不同的實現。

和封裝繼承一樣,多態不僅可以改善代碼的組織結構和可讀性,還可以讓程序更加具有可擴展性。

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

[6] https://www.jb51.net/article/194529.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章