接口 抽象类 C++
1. 數據抽象
數據抽象是指,只向外界提供關鍵信息,并隱藏其后臺的實現細節,即只表現必要的信息而不呈現細節。
數據抽象是一種依賴于接口和實現分離的編程(設計)技術。
讓我們舉一個現實生活中的真實例子,比如一臺電視機,您可以打開和關閉、切換頻道、調整音量、添加外部組件(如喇叭、錄像機、DVD 播放器),但是您不知道它的內部實現細節,也就是說,您并不知道它是如何通過纜線接收信號,如何轉換信號,并最終顯示在屏幕上。
因此,我們可以說電視把它的內部實現和外部接口分離開了,您無需知道它的內部實現原理,直接通過它的外部接口(比如電源按鈕、遙控器、聲量控制器)就可以操控電視。
現在,讓我們言歸正傳,就 C++ 編程而言,C++ 類為數據抽象提供了可能。它們向外界提供了大量用于操作對象數據的公共方法,也就是說,外界實際上并不清楚類的內部實現。
例如,您的程序可以調用?sort()?函數,而不需要知道函數中排序數據所用到的算法。實際上,函數排序的底層實現會因庫的版本不同而有所差異,只要接口不變,函數調用就可以照常工作。
在 C++ 中,我們使用類來定義我們自己的抽象數據類型(ADT)。您可以使用類?iostream?的?cout?對象來輸出數據到標準輸出,如下所示:
在這里,您不需要理解?cout?是如何在用戶的屏幕上顯示文本。您只需要知道公共接口即可,cout 的底層實現可以自由改變。
訪問標簽強制抽象
在 C++ 中,我們使用訪問標簽來定義類的抽象接口。一個類可以包含零個或多個訪問標簽:
- 使用公共標簽定義的成員都可以訪問該程序的所有部分。一個類型的數據抽象視圖是由它的公共成員來定義的。
- 使用私有標簽定義的成員無法訪問到使用類的代碼。私有部分對使用類型的代碼隱藏了實現細節。
訪問標簽出現的頻率沒有限制。每個訪問標簽指定了緊隨其后的成員定義的訪問級別。指定的訪問級別會一直有效,直到遇到下一個訪問標簽或者遇到類主體的關閉右括號為止。
數據抽象的好處
數據抽象有兩個重要的優勢:
- 類的內部受到保護,不會因無意的用戶級錯誤導致對象狀態受損。
- 類實現可能隨著時間的推移而發生變化,以便應對不斷變化的需求,或者應對那些要求不改變用戶級代碼的錯誤報告。
如果只在類的私有部分定義數據成員,編寫該類的作者就可以隨意更改數據。如果實現發生改變,則只需要檢查類的代碼,看看這個改變會導致哪些影響。如果數據是公有的,則任何直接訪問舊表示形式的數據成員的函數都可能受到影響。
數據抽象的實例
C++ 程序中,任何帶有公有和私有成員的類都可以作為數據抽象的實例。請看下面的實例:
設計策略
抽象把代碼分離為接口和實現。所以在設計組件時,必須保持接口獨立于實現,這樣,如果改變底層實現,接口也將保持不變。
在這種情況下,不管任何程序使用接口,接口都不會受到影響,只需要將最新的實現重新編譯即可。
2. 接口與抽象類
接口描述了類的行為和功能,而不需要完成類的特定實現。
C++ 接口是使用抽象類來實現的,抽象類與數據抽象互不混淆,數據抽象是一個把實現細節與相關的數據分離開的概念。
如果類中至少有一個函數被聲明為純虛函數,則這個類就是抽象類。純虛函數是通過在聲明中使用 "= 0" 來指定的,如下所示:
class Box {public:// 純虛函數virtual double getVolume() = 0;private:double length; // 長度double breadth; // 寬度double height; // 高度 };設計抽象類(通常稱為 ABC)的目的,是為了給其他類提供一個可以繼承的適當的基類。抽象類不能被用于實例化對象,它只能作為接口使用。如果試圖實例化一個抽象類的對象,會導致編譯錯誤。
因此,如果一個 ABC 的子類需要被實例化,則必須實現每個虛函數,這也意味著 C++ 支持使用 ABC 聲明接口。如果沒有在派生類中重寫純虛函數,就嘗試實例化該類的對象,會導致編譯錯誤。
可用于實例化對象的類被稱為具體類。
抽象類只能作為父類被繼承,且子類必須實現存續函數,實現后的函數在子類中是虛函數。抽象類不能定義對象,但是抽象類可以定義指針。
C++中接口設計滿足如下幾個基本條件:
(1)類中沒有定義任何的成員變量
(2)所有成員函數都是共有的
(3)所有成員函數都是純虛函數
(4)接口是一種特殊的抽象類
#include <iostream> #include <string>using namespace std;class Channel { public:virtual bool open() = 0;virtual void close() = 0;virtual bool send(char* buf, int len) = 0;virtual int receive(char* buf, int len) = 0; };int main() {return 0; }設計策略
面向對象的系統可能會使用一個抽象基類為所有的外部應用程序提供一個適當的、通用的、標準化的接口。然后,派生類通過繼承抽象基類,就把所有類似的操作都繼承下來。
外部應用程序提供的功能(即公有函數)在抽象基類中是以純虛函數的形式存在的。這些純虛函數在相應的派生類中被實現。
這個架構也使得新的應用程序可以很容易地被添加到系統中,即使是在系統被定義之后依然可以如此。
3. C++對外提供庫
使用C++開發語言開發程序,C++分裝成的類庫文件通過接口方式直接對外提供對應的接口調用方式。首先定義接口類,實現類繼承接口實現接口函數,最終外部直接使用接口來對模塊或者庫進行操作,而不會對內部代碼有復雜的更改。
class interface {public:static interface *create();virtual int add(int a, int b) = 0; }; #include <interface.h>class interfaceimpl : public interface {public:int add(int a, int b){return a+ b;} };interface* interface::create() {return new interfaceimpl; // C++11可以使用只能指針方式來實現 } #include <stdio.h> #include <interface.h>int main() {interface *in = interface::create();int c = in->add(2, 3);printf("c : %d\n", c);return 0; }提供C++語言形式的頭文件時,我們不希望暴露太多的細節,因此,一般定義一個抽象接口,然后把這個接口頭文件提供出去。
這個抽象接口還必須有一個靜態的工廠函數,而這個工廠函數的具體實現也是在庫里面實現。 通過這個工廠函數就可以將真正的
類對象創建出來,這個類對象是繼承并實現了接口類的。
抽象類的介紹
抽象類是一種特殊的類,它是為了抽象和設計的目的為建立的,它處于繼承層次結構的較上層。
-
(1)抽象類的定義:稱帶有純虛函數的類為抽象類。
-
(2)抽象類的作用:抽象類的主要作用是將有關的操作作為結果接口組織在一個繼承層次結構中,由它來為派生類提供一個公共的根,派生類將具體實現在其基類中作為接口的操作。所以派生類實際上刻畫了一組子類的操作接口的通用語義,這些語義也傳給子類,子類可以具體實現這些語義,也可以再將這些語義傳給自己的子類。
-
(3)使用抽象類時注意:a、抽象類只能作為基類來使用,其純虛函數的實現由派生類給出。如果派生類中沒有重新定義純虛函數,而只是繼承基類的純虛函數,則這個派生類仍然還是一個抽象類。如果派生類中給出了基類純虛函數的實現,則該派生類就不再是抽象類了,它是一個可以建立對象的具體的類。b、抽象類是不能定義對象的。
總結:
-
1、純虛函數聲明如下:?virtual void funtion1()=0;?純虛函數一定沒有定義,純虛函數用來規范派生類的行為,即接口。包含純虛函數的類是抽象類,抽象類不能定義實例,但可以聲明指向實現該抽象類的具體類的指針或引用。
-
2、虛函數聲明如下:virtual ReturnType FunctionName(Parameter);?虛函數必須實現,如果不實現,編譯器將報錯,錯誤提示為:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)" -
3、對于虛函數來說,父類和子類都有各自的版本。由多態方式調用的時候動態綁定。
-
4、實現了純虛函數的子類,該純虛函數在子類中就編程了虛函數,子類的子類即孫子類可以覆蓋該虛函數,由多態方式調用的時候動態綁定。
-
5、虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。
-
6、在有動態分配堆上內存的時候,析構函數必須是虛函數,但沒有必要是純虛的。
-
7、友元不是成員函數,只有成員函數才可以是虛擬的,因此友元不能是虛擬函數。但可以通過讓友元函數調用虛擬成員函數來解決友元的虛擬問題。
-
8、析構函數應當是虛函數,將調用相應對象類型的析構函數,因此,如果指針指向的是子類對象,將調用子類的析構函數,然后自動調用基類的析構函數。
有純虛函數的類是抽象類,不能生成對象,只能派生。他派生的類的純虛函數沒有被改寫,那么,它的派生類還是個抽象類。
定義純虛函數就是為了讓基類不可實例化化
因為實例化這樣的抽象數據結構本身并沒有意義。
或者給出實現也沒有意義
實際上我個人認為純虛函數的引入,是出于兩個目的
-
1、為了安全,因為避免任何需要明確但是因為不小心而導致的未知的結果,提醒子類去做應做的實現。
-
2、為了效率,不是程序執行的效率,而是為了編碼的效率。
總結
以上是生活随笔為你收集整理的接口 抽象类 C++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: form表单提交,action需要加项目
- 下一篇: s3c2440移植MQTT