程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Effective C++:條款41:了解隱式接口和編譯期多態

Effective C++:條款41:了解隱式接口和編譯期多態

編輯:C++入門知識

Effective C++:條款41:了解隱式接口和編譯期多態


(一)

首先看下面的類以及函數:

class Widget {
public:
	Widget();
	virtual ~Widget();
	virtual size_t size() const;
	virtual void normalize();
	virtual swap(Widget& other);
};
void doProcessing(Widget& w) {
	if(w.size() < 10 && w != someNastyWidget) {
		Widget temp(w);
		temp.normalize();
		temp.swap(w);
	}
}

由於w被聲明為Widget,所以w必須支持Widget接口。我們可以在源碼中找到這個接口(例如在widget.h中),看看它是什麼樣子,所以我們稱此為一個顯式接口,也就是它在源碼中明確可見。

Widget某些成員函數是virtual,w對那些函數的調用表現出運行期多態,運行期根據w的動態類型決定究竟調用哪個函數。

(二)

template及泛型編程的世界,與面向對象有著根本的不同。隱式接口和編譯期多態移到了前頭:

template
void doProcessing(T& w) {
	if(w.size() > 10 && w != someNastyWidget) {
		T temp(w);
		temp.normalize();
		temp.swap(w);
	}
}

w必須支持哪一種接口,由template中執行與w身上的操作來決定。本例w的類型T必須支持size,normalize和swap成員函數,copy構造函數、不等比較!=,並非完全正確。這一組表達式便是T必須支持的一組隱式接口。

凡涉及w的任何調用,例如operator!=,有可能造成template的具現化,是這些調用得以成功。這樣的具現化發生在編譯期。“以不同的template參數具現化function template”會導致調用不同的參數,這便是編譯期多態(compile-time polymorphism)。類似於“哪個重載函數被調用”(發生在編譯期)和“哪一個virtual函數被調用”(發生在運行期)之間的差異。

顯式接口由函數的簽名式(名稱、參數類型、返回類型)構成:例如

class Widget{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
virtual swap(Widget& other);
};

除了上面的還有編譯期產生的copy構造函數和copy assignment操作符。另外也可以包括typedefs等。

隱式接口不基於函數簽名式,而是由有效表達式(valid expressions)組成。

template 
void doProcessing(T& w) 
{ 
    if (w.size() > 10 && w != someNastyWidget){ 
        T temp(w); 
        temp.normalize(); 
        temp.swap(w); 
    } 
}

T(w的類型)的隱式接口好像有這些約束:

必須提供一個size成員函數;

必須支持operator!=;

真要感謝操作符重載帶來的可能性,這兩個約束都不需要滿足。

原因:

T必須支持size成員函數,然而這個函數可以從base class繼承而得。這個函數不需要返回一個整數值,他唯一要做的是返回一個類型為X的對象,而X對象加上一個int(10)必須能夠調用一個operator>。這個operator>可以取得類型為Y的參數,只要存在一個隱式轉換能將類型X的對象轉換為類型Y的對象。

同樣道理T並不需要支持operator!=,operator!=只要階接受一個類型為X和Y的對象,T可以轉換為X而someNastyWidget可以轉換成Y。

加諸於template參數身上的隱式接口,就像加諸於class對象身上的顯式接口一樣真實,都在編譯期完成檢查。


請記住:

(1)class和template都支持接口和多態。

(2)對classes而言,接口是顯式的(explicit),以函數簽名為中心。多態則是通過virtual函數發生在運行期。

(3)對template參數而言,接口是隱式的(implicit),奠基於有效表達式。多態則是通過template具現化和函數重載解析(function overloading resolution)發生在編譯期。











  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved