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