通常顯式接口由函數的簽名式(函數名稱、參數類型、返回類型)構成。例如
Widget class:
class Widget{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap( Widget& other );
};
其public接口由一個構造函數、析構函數、函數size、normalize、swap及其參數類型、返回類型、常量性構成。
隱式接口就完全不一樣了。它並不基於函數簽名式,而是由有效表達式組成。例如下面的模板函數doProcessing:
template<typename T>
void doProcessing( T& w ){
if( w.size() > 10 && w != someNastyWidget )
...
}
T的隱式接口看起來好像有這些約束:
(1)它必須提供一個名爲size的成員函數,該函數返回一個整數值。
(2)它必須支持一個operator!=函數,用來比較兩個T對象,
但其實這兩個約束都不需要滿足。T必須支持size函數,但是這個函數也可能從base class繼承而得;這個成員函數不一定需要返回一個整數值,甚至不需要返回一個數值類型。它唯一需要做的是返回一個類型爲X的對象,該對象加上一個int型後可以調用一個operator>。同樣道理,T也不需要支持operator!=,只要存在一個operator!=,它接受一個類型爲X的對象和一個類型爲Y的對象,T可被轉換爲X而someNastyWidget可被轉換爲Y。
總結起來,
對class而言,接口是顯式的,以函數簽名爲中心。多態則是通過virtual函數發生於運行期。
對template參數而言,接口是隱式的,基於有效表達式。多態則是通過template具現化和函數重載解析,發生於編譯期。