oop都是以顯示接口和運行期多態解決問題;
Template和泛型編程以隱式接口和編譯期多態解決問題。
----------------------------------------------------------------------------------------------------------------------------------------------
classes和template都支持接口和多態。
對於classes而言接口是顯式的,以函數簽名為中心;多態是通過virtual函數發生在運行期。
對於template而言接口是隱式的,取決於有效表達式;多態是通過template具現化和函數重載解析發生於編譯期。
----------------------------------------------------------------------------------------------------------------------------------------------
class Widget
{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
};
顯示接口由函數的簽名式(函數名稱、參數類型、返回類型)構成:
一個構造函數、一個析構函數、函數size、normalize、swap以及其參數類型、返回類型、常量性構成;
當然也包括編譯期產生的copy構造函數、copy assignment操作符。另外也可以包括typedef。
運行期多態:
由於有virtual函數,那麼函數的調用將取決於運行期w的動態類型。(換句話說就是,virtual函數的調用不在編譯期決定,而是在運行期決定調用哪個virtual函數:base class的版本還是derived class的版本)
template<typename T>
void doProcessing( T& w)
{
if(w.size() > 10 && w != someNsatyWifget)
{…}
}
隱式接口並不基於函數的簽名式。而是由有效表達式組成:
T的隱式接口看起來好像有這麼約束:
1.他必須提供一個名為size的函數,該函數返回一個整數值。
2.他必須支持一個opreator!=函數,用來比較家兩個T對象。這裡我們假設someNastyWidget的類型是T。
size成員函數可能是從base class 繼承而來的,所以它不需要返回一個數值類型。
T並不需要支持opreator!=,因為opreator!=接收一個類型為x的對象那個和一個類型為y的對象,T可被轉換為x而someNastyWidget的類型可被轉換成y,這樣就可以有效調用!=了。
雖然具體確定隱式接口很難,但是我們整體確認表達式約束條件卻很簡單,if語句的條件句必須是個布爾表達式。這是template doProcessing加諸於其類型參數T的隱式接口的一部分。其他的隱式接口是:copy構造函數、normalize和swap也都必須對T類型對象有效。
編譯期多態:
對於w的任何函數調用,都有可能造成template具現化。
這些行為發生在編譯期。
以不同的template參數具現化function template會導致調用不同的函數,這就是編譯期多態。
Ps:顯示接口和隱式接口都在編譯期完成檢查。