多態是指通過單一的標識支持不同的特定行為的能力。
C++中有兩種多態,稱為動多態(運行期多態)和靜多態(編譯期多態),而靜多態主要通過模板來實現,宏也是實現靜多態的一種途徑。
動多態在C++中是通過虛函數實現的,即在基類中存在一些接口(一般為純虛函數),子類必須重載這些接口。這樣通過使用基類的指針或者引用指向子類的對象,就可以實現調用子類對應的函數的功能。動多態的函數調用機制是執行期才能進行確定,所以它是動態的。
#include <iostream> using namespace std; class shape { public: virtual void draw() = 0; }; class line : public shape { public: void draw() { cout << "line is drawing!" << endl; } }; class circle : public shape { public: void draw() { cout << "circle is drawing!" << endl; } }; int main() { shape* pLine = new line; shape* pCircle = new circle; // line line; // circle circl; // // shape& referenceLine = line; //引用 // shape& referenceCircl = circl; // // referenceLine.draw(); // referenceCircl.draw(); pLine->draw(); pCircle->draw(); if( pCircle ) delete pCircle ; if( pLine ) delete pLine ; return 0; }
靜多態是采用模板機制實現的,沒用基類,因此也不用進行綁定。它不采用虛函數機制,所以所有調用在編譯期就可確定,因此它是靜態的。
#include <iostream> using namespace std; class line { public: void draw() { cout << "line is drawing!" << endl; } }; class circle { public: void draw() { cout << "circle is drawing!" << endl; } }; template<typename T> void drawShape(T & shape) { shape.draw(); } int main() { line lining; circle circling; drawShape( lining ); drawShape( circling ); return 0; }
動多態的實現要通過虛函數,會產生虛表和虛指針,占用較多的空間,動多態需要在運行期進行綁定,所花費的時間較靜多態多。
優點:能處理異類集合(容器中存儲基類指針即可)、可執行代碼比較小(只需一個多態函數)、可以完全編譯而不需要發布源碼。
缺點:不能提前檢查類型的安全性(如向容器中插入錯誤類型的對象)、性能低(有層層繼承)、耦合性高(繼承的耦合性高於組合)。
靜多態在空間和時間上都比動多態表現的好,因此在其他的條件相同的情況下,應該更多的使用靜多態。但是靜多態也有一些缺點,如它不能夠處理異類的集合,也沒有動多態靈活。並且現在大部分編譯器不支持模板的分離編譯,因此要將聲明和實現寫在一個文件中,這樣會暴露更多的細節。
優點:具體類可以只實現需要的接口、生成代碼性能高(無需通過指針的間接調用,非虛函數具有更多的內聯機會)、有更好的類型安全性(類型在編譯期就進行檢查)、耦合性低(各個類相互獨立)、集合的元素類型不再局限於指針。
缺點:不能處理異類集合、可執行代碼比較大(代碼膨脹)、模板庫源碼需要發布、對模板實參類型有約束(比如需要該類型實現了operator<)。
到底用動多態還是靜多態,應該根據情況綜合考慮決定。我們也可以結合動多態和靜多態來獲得一個很好的效率和靈活性。
