抽象基類(ABC)

2021-09-10 14:20:11 字數 3704 閱讀 2650

我對抽象基類(abstract base class,abc)的理解在兩個點上。第一點是抽象,即高度抽象;第二點是基類,對抽象基類來說,它的存在只是為了作為基類(區別於具體類),不可以被例項化

高度抽象一詞聽起來本身就很「抽象」,不妨讓我用「總結」這個詞進行通俗解釋。比方這裡有兩類人,一類只是聾人,另一類只是盲人。現在我們需要對這兩類人抽象,也就是需要總結兩類人的相同點+不同點,然後付諸於**。為方便起見,這裡就列舉三個行為:散步為相同點,看得見與看不見為不同點,聽得見與聽不見為不同點——這樣乙個過程,就是在「抽象」。(好吧,這般解釋可能還是抽象)

在c++中,virtual關鍵字使得函式有虛函式非虛函式之分,顯然,virtual的存在讓乙個函式成為虛函式。而虛函式中,又分純虛函式和非純虛函式:

virtual

void

hear()

=0;// 純虛函式

virtual

void

walk()

;// 非純虛函式(常規虛函式)

在乙個類中,如果至少有乙個純虛函式,那麼認為這個類是抽象基類。

class

deafperson

;// ...

如此一來,deafperson就是乙個抽象基類了。

我們都知道,無論盲人還是聾人,他們都是人,他們都可以散步,但是不一定有視覺或聽覺的能力。我們當然可以做以下設計:

class

deafperson

void

hear()

void

see()}

;class

blindperson

void

hear()

void

see()}

;

顯然,由於我們只找了乙個相同行為,所以只重複了walk()函式,但倘若在我們的需求裡有必要用到多個相同行為,比如吃東西、聊天、穿衣……如果仍用以上方式,那對每個類都不得不定義乙個eat()函式、chat()函式、wear()函式……為了偷懶,我們很快想到再抽象乙個person類出來,用繼承的方式實現**復用,像下面那樣:

class

person

/* 共有的能力 */

void

walk()

void

eat(

)void

wear()

/* 可能需要重寫的部分 */

void

hear()

void

see()}

;class

deafperson

:public person

/* 使用父類的建構函式 */

void

hear()

};class

blindperson

:public person

;void

see()}

;int

main()

// 輸出:

lily is able to walk

lily is not able to hear

boby is able to eat

boby is not able to see

可這樣做的缺點是,也許設計person類和deafperson類是兩個人,兩人之間卻不曾約定,那麼設計deafperson時存在忘記重寫hear()方法的可能。所以現在得有個規定,如果子類中沒有重寫父類中的某個方法,就不允許子類例項化,這樣一來,設計deafperson的人就不得不重寫必需方法了。

person類設計如下:

class

person

void

walk()

void

eat(

)void

wear()

/* 必需重寫的部分 */

virtual

void

hear()

=0;/* 必需重寫的函式設計為 純虛函式 */

virtual

void

see()=

0;/* 必需重寫的函式設計為 純虛函式 */

};

倘若deafperson繼承person後卻不重寫hear()方法和see()方法,對它例項化,編譯器就會報錯:

d:\mycode\cc++\abs_study\main.cpp(37): error c2259: 「deafperson」: 不能例項化抽象類

d:\mycode\cc++\abs_study\main.cpp(37): note: 由於下列成員:

d:\mycode\cc++\abs_study\main.cpp(37): note: 「void person::hear(void)」: 是抽象的

d:\mycode\cc++\abs_study\main.cpp(16): note: 參見「person::hear」的宣告

d:\mycode\cc++\abs_study\main.cpp(37): note: 「void person::see(void)」: 是抽象的

d:\mycode\cc++\abs_study\main.cpp(17): note: 參見「person::see」的宣告

道理很簡單,抽象基類不可以例項化,而子類繼承父類之後沒有重寫父類中的純虛函式,對於子類來說,它也擁有了這些純虛函式,所以子類也是抽象基類,因此也不能例項化。按規定,要在子類中用常規虛函式實現這些介面,像這樣:

class

deafperson

:public person

virtual

void

hear()

virtual

void

see()}

;

使用抽象基類的另一好處是,因為子類們繼承自同一父類,用父類型別的指標或引用進行管理可以簡化**。

person *deaf,

*blind;

/* 基類型別指標 */

deaf =

newdeafperson

("lily");

deaf-

>

walk()

;deaf-

>

hear()

;blind =

newblindperson

("boby");

blind-

>

eat();

blind-

>

see(

);

void

print_name

(person& person)

/* 基類引用 */

intmain()

// 輸出:

lily

boby

void person::

hear()

void person::

see(

)

C 基礎 抽象基類(ABC)

抽象基類 abc 即abstract base class利用了基類指標指向派生類物件從而呼叫派生類方法的思想實現c 的隱藏 具體實現則主要用到的是純虛函式 pragma once include stdafx.h include include using std cout using std e...

3 2 抽象基類(abc模組)

實現乙個抽象基類,不適用abc模組 1 class base 2def get self,key 3raise notimplemented45 defset self,key,value 6raise notimplemented78 9class test base 10def get self...

ACM 抽象基類

檔名稱 完成日期 2014年6月3日 版本號 v0.1 對任務及求解方法的描述部分 輸入描述 無 問題描述 程式輸入 程式輸出 問題分析 演算法設計 我的程式 include include using namespace std class shape class circle public sh...