C++:如何正確的定義一個接口類


C++中如何定義接口類?
首先給接口類下了定義:接口類應該是只提供方法聲明,而自身不提供方法定義的抽象類。接口類自身不能實例化,接口類的方法定義/實現只能由接口類的子類來完成。

而對於C++,其接口類一般具有以下特征:

1.最好不要有成員變量,但可以有靜態常量(static const或enum)
2.要有純虛接口方法
3.要有虛析構函數,並提供默認實現
4.不要聲明構造函數

如下就是一個最簡單的例子:

class Testable
{
public:
static const int START = 1; // #1
static const int STOP = 2;

virtual void test() = 0; // #2: 接口方法

virtual ~Testable() {}; // #3: 從C++11開始可以: virtual ~Testable() = default;
}
#1.
如果成員變量,尤其是可變的成員變量,定義在接口中,等於是把實現細節暴露出來了,不符合接口定義的要求,所以一般不在接口中定義可變的成員變量。
而常量可以定義在接口中,因為有時接口需要返回狀態,而這些狀態可以定義成常量放在接口中。

#2.
由於不能讓接口類自身能夠實例化,並且需要子類必須實現接口暴露的方法,所以接口方法都要聲明成純虛函數。
聲明成純虛函數意味着接口類自身不需要提供方法的定義,方法的定義需要由接口類的子類提供,並且接口類自身也因此變成了抽象類而不能被實例化。

#3.
a). 在使用接口類的指針訪問接口類的子類的實例時,當對接口類的指針做delete時,如果接口類的析構函數不是虛析構函數的話,將只會調用接口類的析構函數,接口類的子類的析構函數將不會被調用,內存泄露將會產生,所以接口類的析構函數必須定義成虛析構函數。
b). 如果接口類的析構函數不提供默認實現,即如果接口類的析構函數是純虛析構函數的話,接口類的子類將被迫必須提供析構函數的實現,這樣對接口類的子類不友好。
c). 在C++11中也可以用:  virtual ~Testable() = default; 替代 virtual ~Testable() {};

#4.
不要顯式定義任何的構造函數,但也不要在接口中加入如下代碼來禁止生成構造函數:

Testable() = delete;
Testable(const Testable&) = delete;
因為C++的調用機制要求子類的構造函數調用時一定會先調用父類的構造函數,如果禁止生成構造函數,代碼編譯時會報錯。如果程序員不顯式的提供構造函數,編譯器也會隱式的加上構造函數的,雖然這些構造函數對於接口類來說實際沒有什么意義。

C++中如何定義標識接口(marker interface)類?
標識接口是沒有任何方法和屬性的接口。這種接口在java中出現的較多,比如:java.io.Serializable、java.rmi.Remote、java.util.EventListener、java.util.RandomAccess

實現代碼如下:

class Testable {
public:
virtual ~Testable() = 0 {}; // #5
};
#5.
只要對純虛析構函數提供一個默認實現就可以了。這種對純虛函數提供實現的寫法看似很奇怪,但C++的確是支持的。

 

以上是定義C++接口類的一些重要事項,如果有錯誤或遺漏,請指正。

另外,對於如何正確的使用接口類,請參看下一篇文章“C++:如何正確的使用接口類”。
---------------------
作者:netyeaxi
來源:CSDN
原文:https://blog.csdn.net/netyeaxi/article/details/80724557


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM