我對抽象基類(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...