虛基類、純虛函式和抽象類
1、虛基類
在《多繼承》中講過的例子中,由類a,類b1和類b2以及類c組成了類繼承的層次結構。在該結構中,類c的物件將包含兩個類a的子物件。由於類a是派生類c兩條繼承路徑上的乙個公共基類,那麼這個公共基類將在派生類的物件中產生多個基類子物件。如果要想使這個公共基類在派生類中只產生乙個基類子物件,則必須將這個基類設定為虛基類。
虛基類的引入和說明
前面簡單地介紹了要引進虛基類的原因。實際上,引進虛基類的真正目的是為了解決二義性問題。
虛基類說明格式如下:
virtual 《繼承方式》《基類名》
其中,virtual是虛類的關鍵字。虛基類的說明是用在定義派生類時,寫在派生類名的後面。例如:
class a
;
class b : virtual public a
;
class c : virtual public a
;
class d : public b, public c
;
由於使用了虛基類,使得類a,類b,類c和類d之間關係用dag圖示法表示如下:
a
/ /
b c
/ /
d
從該圖中可見不同繼承路徑的虛基類子物件被合併成為乙個物件。這便是虛基類的作用,這樣將消除了合併之前可能出現的二義性。這時,在類d的物件中只存在乙個類a的物件。因此,下面的引用都是正確的:
d n;
n.f(); //對f()引用是正確的。
void d::g()
下面程式段是正確的。
d n;
a *pa;
pa = &n;
其中,pa是指向類a物件的指標,n是類d的乙個物件,&n是n物件的位址。pa=&n是讓pa指標指向類d的物件,這是正確的,並且也無二義性。
虛基類的建構函式
前面講過,為了初始化基類的子物件,派生類的建構函式要呼叫基類的建構函式。對於虛基類來講,由於派生類的物件中只有乙個虛基類子物件。為保證虛基類子物件只被初始化一次,這個虛基類建構函式必須只被呼叫一次。由於繼承結構的層次可能很深,規定將在建立物件時所指定的類稱為最派生類。c++規定,虛基類子物件是由最派生類的建構函式通過呼叫虛基類的建構函式進行初始化的。如果乙個派生類有乙個直接或間接的虛基類,那麼派生類的建構函式的成員初始列表中必須列出對虛基類建構函式的呼叫。如果未被列出,則表示使用該虛基類的預設建構函式來初始化派生類物件中的虛基類子物件。
從虛基類直接或間接繼承的派生類中的建構函式的成員初始化列表中都要列出這個虛基類建構函式的呼叫。但是,只有用於建立物件的那個最派生類的構造函式呼叫虛基類的建構函式,而該派生類的基類中所列出的對這個虛基類的構造函式呼叫在執行中被忽略,這樣便保證了對虛基類的物件只初始化一次。
c++又規定,在乙個成員初始化列表中出現對虛基類和非虛基類建構函式的呼叫,則虛基類的建構函式先於非虛基類的建構函式的執行。
下面舉一例子說明具有虛基類的派生類的建構函式的用法。
#include
class a
;
在許多情況下,在基類中不能對虛函式給出有意義有實現,而把它說明為純虛函式,它的實現留給該基類的派生類去做。這就是純虛函式的作用。下面給出乙個純虛函式的例子。
#include
class point
virtual void set() = 0;
virtual void draw() = 0;
protected:
int x0, y0;
};
class line : public point
void set()
void draw()
protected:
int x1, y1;
};
class ellipse : public point
void set()
void draw()
protected:
int x2, y2;
};
void drawobj(point *p)
void setobj(point *p)
#include
#include "test.h"
using namespace std;
int main()
抽象類帶有純虛函式的類稱為抽象類。抽象類是一種特殊的類,它是為了抽象和設計的目的而建立的,它處於繼承層次結構的較上層。抽象類是不能定義物件的,在實際中為了強調乙個類是抽象類,可將該類的建構函式說明為保護的訪問控制許可權。
抽象類的主要作用是將有關的組織在乙個繼承層次結構中,由它來為它們提供乙個公共的根,相關的子類是從這個根派生出來的。
抽象類刻畫了一組子類的操作介面的通用語義,這些語義也傳給子類。一般而言,抽象類只描述這組子類共同的操作介面,而完整的實現留給子類。
抽象類只能作為基類來使用,其純虛函式的實現由派生類給出。如果派生類沒有重新定義純虛函式,而派生類只是繼承基類的純虛函式,則這個派生類仍然還是乙個抽象類。如果派生類中給出了基類純虛函式的實現,則該派生類就不再是抽象類了,它是乙個可以建立物件的具體類了。
----摘自《c++物件導向程式設計基礎教程》
虛基類,抽象類,虛函式,純虛函式,virtual
虛基類 在說明其作用前先看一段 class a class b public a class b virtual public a 大家以為這段 的輸出結果是什麼?有的人可能會馬上回答funprint of class a 與 funprint of class b 因為第一次輸出是引用類a的實 例...
虛基類 虛函式 純虛函式和抽象類
一 虛基類 在 多繼承 中講過的例子中,由類a,類b1和類b2以及類c組成了類繼承的層次結構。在該結構中,類c的物件將包含兩個類a的子物件。由於類a是派生類c兩條繼承路徑上的乙個公共基類,那麼這個公共基類將在派生類的物件中產生多個基類子物件。如果要想使這個公共基類在派生類中只產生乙個基類子物件,則必...
虛函式 虛基類 抽象類
一 虛基類 解決二義性,防止雙份拷貝間接基類。否則得用作用域分辨符來區分進行的多個拷貝 將共同基類設定為虛函式,這是從不同的路徑繼承過來的同名資料成員在記憶體中就只有乙個拷貝,同乙個函式名也只有乙個對映。虛基類的宣告是在派生類的定義過程中進行的,語法形式為 class 派生類名 virtual繼承方...