c++中的抽象概念詳解

weixin_34054866發表於2013-06-13

一、定義.

在物件導向的概念中,我們知道所有的物件都是通過類來描繪的,但是反過來卻不是這樣。並不是所有的類都是用來描繪物件的, 如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類 。純虛擬函式是在基類中宣告的虛擬函式,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛擬函式的方法是在函式原型後加“=0”。

virtual void funtion1()=0

二、引入原因:

1、為了方便使用多型特性,我們常常需要在基類中定義虛擬函式。

2、在很多情況下,基類本身生成物件是不合情理的。例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身生成物件明顯不合常理。

 為了解決上述問題,引入了純虛擬函式的概念,將函式定義為純虛擬函式,則編譯器要求在派生類中必須予以過載以實現多型性。同時含有純虛擬函式的類稱為抽象類,它不能生成物件

 

三、相似概念:

 1、多型性

 指相同物件收到不同訊息或不同物件收到相同訊息時產生不同的實現動作。C++支援兩種多型性:編譯時多型性,執行時多型性。

a.編譯時多型性:通過過載函式實現

b 執行時多型性:通過虛擬函式實現。

 

2、虛擬函式

 虛擬函式是在基類中被宣告為virtual,並在派生類中重新定義的成員函式,可實現成員函式的動態過載

 

3、抽象類

 包含純虛擬函式的類稱為抽象類。由於抽象類包含了沒有定義的純虛擬函式,所以不能定義抽象類的物件。

四、程式

 

基類:
class A
{
public:
A();
void f1();
virtual void f2();
virtual void f3()=0;
virtual ~A();

};

子類:
class B : public A
{
public:
B();
void f1();
void f2();
void f3();
virtual ~B();

};
主函式:
int main(int argc, char* argv[])
{
A *m_j=new B();
m_j->f1();
m_j->f2();
m_j->f3();
delete m_j;
return 0;
}

程式解釋:

 

 

f1()是一個普通的過載.

呼叫m_j->f1();會去呼叫A類中的f1(),它是在我們寫好程式碼的時候就會定好的.

也就是根據它是由A類定義的,這樣就呼叫這個類的函式.

f2()是虛擬函式.

呼叫m_j->f2();會呼叫m_j中到底儲存的物件中,對應的這個函式.這是由於new的B

物件.

f3()與f2()一樣,只是在基類中不需要寫函式實現. 

五、總結

 

       抽象就是把有共同屬性或方法的抽象成一個類實現不了自己定義的介面(純虛擬函式)就是抽象類。反過來想。如:我們定義了動物的類,屬性是有嘴,方法是 吃。我們沒有定義吃的具體實現。在派生類 老虎裡 定義了 吃的 具體實現  吃肉,派生類 牛 裡定義了 吃 的 具體實現 吃草,這就說明動物這個類 是抽象類,決定不了吃的具體實現,必須實現了吃 這個介面的類才不是抽象的類。如果實現了 吃的方法,那動物這個類就不能就不能通過介面說明 它是個抽象類。

      定義純虛擬函式就是把派生類裡的共同的方法抽象出來放到基類裡,但並沒有具體實現(描述)(因為是抽象的無法具體描述物件),派生類裡對這些共同的方法來描述。如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類。把’吃肉‘,’吃草‘的共同方法’吃‘提取出來,那麼動物就是抽象類。

      將函式定義為純虛擬函式能夠說明,該函式為後代型別提供了可以覆蓋的介面,但是這個類中的版本決不會呼叫。

 

     為什麼說只要擁有純虛擬函式的類就是抽象類?

     派生類能夠描述物件的資訊,而基類類卻不能描述此類物件的資訊(即純虛擬函式),就是抽象類。

     抽象類定義是物件有共同屬性或方法抽象成一個類,但無法描述具體的物件(肯定無法描述),它是不存在的

     首先基類裡 存在著派生類的 共同的屬性 方法,但是如果是虛擬函式的話,基類的方法就和派生不一樣了,因為虛擬函式是動態繫結,它改寫基類的虛擬函式後,就與基類的實現不同了,這樣基類就沒有提取派生類的共同方法,基類也不是抽象類。如果定義為純虛擬函式,則基類的純虛擬函式就是個介面,純虛擬函式不能被呼叫,它的存在只是為了在派生類中重新定義。通過純虛擬函式的定義來確定抽象類以區別具體類。(同樣的方法因為派生類能夠呼叫而基類不能呼叫,所以是抽象類)抽象類也就是無法例項化。




相關文章