在C++中,以類、虛函數等為代表的數據抽象功能一直是C++的核心和難點。這裡我想結合自己的使用經驗,談談對C++中抽象的一點淺薄看法!
我認為C++的抽象應該是指:從我們需要解決的問題出發,在與該問題相關的一組關聯對象中提取出主要的或共有的部分――說簡單一點,就是用相同的行為來操作不同的對象。
從提出問題到找出與該問題相關的對象,這是一個互動的、反復的過程。在對相關對象的抽象中,隨著認識的深入,我們可能會修改最初的目標,而最初目標的修改又可能使一組新的相關對象被加入進來。如:假設現在要設計一個基於廣域網的郵件服務器,首先可能需要通過socket對底層協議進行封裝,為高層的pop3、smtp協議提供一組標准的接口。開始為了使問題簡化我們可能計劃只封裝TCP/IP協議,不過基於以下兩點我們有理由修改最初的需求:
1、pop3、smtp需要的底層接口很簡單。除了連接,僅需要發送、接收一塊數據的功能
2、用socket進行網絡編程,大多數常見協議間的差別很小,有許多都僅僅只是初始化和連接不同而已我們只需要做很小的努力就可以兼容大多數常用協議(如:ATM、Ipx、紅外線協議等)。
現在決定修改需求,除了TCP/IP協議,還要支持一些其他的的常用協議。通過對最初目標的修改,除了TCP/IP協議對象,又會有一組相關的協議對象被加入進來。我們可以很容易從這組相關對象中提出共有的部分,將他抽象到另一個公共對象中。當然,根據具體應用環境不同,這可能並不是最佳方案。
C++中常規的抽象是在一組相互間有“血緣”關系的類中展開的。如:
Class Parent
{
virtual ~Parent(){};
virtual void GetValue(){ .... };
virtual void Test(){ ... };
};
class child1 : public parent
{
virtual ~child1(){};
virtual void GetValue(){...};
virtual void Test(){ ... } const;
};
class child2 : public parent
{
virtual ~child2(){};
virtual void GetValue(){...};
virtual void Test(){ ... } ;
};
(順便說一句,child1::Test() const 不是基類 parent::Test() 的重載。)
由上可總結出C++中抽象的一些基本特點:
1、被抽象對象必須直接或間接派生至某個類對象
2、如果你不用沒有類型安全的操作,如:向下轉型操作或強制類型轉化操作(像COM那樣)。那麼派生類中需要抽象的動作必須在某個基類中出現。
3、基類的析構函數必須是一個虛函數(嗯.... 有點無賴!)
................