有一條基本的設計原則是“對介面編程”,什麼意思呢?就是首先通過介面定義協定,也就是介面能夠對外提供的功能描述,然後通過具體的類實現該介面。下面是個實現舉例
1class IA
2{
3public:
4 virtual void OperationA() = 0;
5};
6class A1 : public IA
7{
8public:
9 virtual void OperationA() {}
10};
這樣的實現擴充比較容易,可以通過新的實作類別提供該介面服務的不同實現版本,比如:1class A2 : public IA
2{
3public:
4 virtual void OperationA() {}
5};
使用程式碼片段如下: IA* a1 = new A1();
a1->OperationA();
delete a1;
IA* a2 = new A1();
a2->OperationA();
delete a2;
如果由於需求的變更導致介面IA必須提供新的服務,這個時候就有兩種選擇:一種是直接在介面IA中加入該服務,另一種是通過介面IA繼承新的介面類型(比如IB),在IB中加入該服務。具體實現如下:1class IA
2{
3public:
4 virtual void OperationA() = 0;
5 virtual void OperationB() = 0;
6};1class IB : public IA
2{
3public:
4 virtual void OperationB() = 0;
5};
這兩種實現都能夠完成任務,區別是前者的變更會導致所有依賴於該介面的具體實作類別或者是介面都必須增加對該新服務的支援,這往往會產生鏈式反應。後者能夠在保證原介面功能不便的情況下加入對新功能的支援。是個不錯的選擇。缺點是如果要使用新服務必須從介面IB繼承
怎樣實現既使用IA介面提供的新功能又不改變依賴於IA代碼呢?答案是使用提供預設實現的虛函數,具體實現如下:1class IA
2{
3public:
4 virtual void OperationA() = 0;
5 virtual void OperationB() {}
6};
這樣具體實作類別型A如果不需要改變該新服務(OperationB)的預設實現,就不需要提供該服務的實現。
純虛函數的介面演化方案和提供預設實現的介面演化方案對應c#中的介面和抽象類別之間的區別。
有興趣的朋友可以看看MSDN Library for Visual Studio 2005上對兩者的使用描述。