1. 程式人生 > >《隨筆十二》—— C++中的 “ 純虛擬函式 和 抽象類 ”

《隨筆十二》—— C++中的 “ 純虛擬函式 和 抽象類 ”

目錄

抽象類

純虛擬函式

抽象類

●   抽象類:  不用於定義物件而只作為一種基本型別用做繼承的類,稱為抽象類, 由於它常用於做基類, 通常稱為抽象基類。 

那麼凡是包含純虛擬函式的類都是抽象類, 抽象類是一種特殊的類, 是為了抽象和設計的目的而建立的, 處於繼承層次結構的較上層。 我們在實際中為了強調一個類是抽象類, 可將該類的建構函式宣告為 保護的訪問控制權限, 這樣我們就不能 在類外建立抽象類的物件,這樣我們就可以在抽象類中的派生類中的建構函式對抽象類的成員資料做初始化。

●  抽象類的主要作用是將有關的類、組織在一個繼承層次結構中, 由抽象類來為它們提供一個公共的介面。 相關的派生類的從這個

抽象類派生出來。抽象類刻畫了一組派生類的操作介面的通用語義,這些語義也傳給了派生類。  一般而言, 抽象類只描述這組派生類公共的操作介面, 而完整的實現留給派生類。  使用抽象類時應注意的問題:

抽象類只能用作其他類的基類, 不能建立抽象類的物件, 因為它的純虛擬函式沒有定義功能, 其純虛擬函式的實現由派生類給出。

但是可以用 基類指標 或 引用 指向 公有(不能是私有或者 保護的)派生類物件(該派生類物件,必須是個具體類,即派生類實現了抽象類中的同名虛擬函式,不再是個純虛擬函式, 否則的話不可以用基類指標 或 引用 指向),然後我們就可以通過該基類指標 或引用呼叫虛擬函式,就可以實現多型操作。

//以下兩種方式都不可以給抽象類建立物件
base myBase;  
base mBase = new base;

如果在派生類中對基類的所有(記住是所有,少一個純虛擬函式的定義,該派生類還是抽象類)純虛擬函式進行了定義, 那麼這些函式就被賦予了功能,就可以被呼叫。 這個派生類就不是個抽象類,而是可以用來定義物件的具體類。   如果在派生類中沒有對所有的純虛擬函式進行定義,則此派生類仍然是抽象類, 不能用來定義物件。

抽象類不能用作引數型別,函式的返回型別 或 顯式轉換的型別。

純虛擬函式

●  當在基類中不能為虛擬函式給出一個有意義的實現時, 可以將其宣告為純虛擬函式。 純虛擬函式的實現可以留給派生類來完成。 那麼純虛擬函式不能被呼叫, 僅僅起到提供一個與派生類一致的介面的作用。 一般來說, 一個抽象類至少有一個純虛擬函式。  純虛擬函式的語法為:

virtual 返回型別  識別符號 (引數表) = 0 ;

純虛擬函式與普通虛擬函式的定義不同在於書寫形式上加了 “ = 0”, 說明在基類中不用定義該函式的函式體, 它並不表示函式返回值為 0, 只起到形式上的作用, 告訴編譯系統它是純虛擬函式。

下面看一個帶有純虛擬函式的抽象類的示例程式:

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

class Shape
{
protected:
	double r;
public:
	Shape(double x)
	{
		r = x;
		cout << "基類的建構函式被呼叫!" << endl;
	}
	~Shape()
	{
		cout << "基類的解構函式被呼叫!" << endl;
	}
	virtual void area() = 0;
	virtual void peri() = 0;
};
class Circle:public Shape
{
private:
	int xx;
public:
	Circle(double x, int _xx) :Shape(x), xx(_xx) 
	{
		cout << "派生類的建構函式被呼叫!" << endl;
	}
	~Circle()
	{
		cout << "派生類的解構函式被呼叫!" << endl;
	}
	virtual void area()
	{
		cout << "圓的面積為:" << 3.14*r*r << endl;
	}
	virtual void peri()
	{
		cout << "圓的周長為:" << 2 * 3.14*r << endl;
	}
};
int main()
{
	//抽象類不可以建立物件
	/*Shape myShape(5.5);
	Shape *mmShape = new Shape(5.5)*/

	{
		Circle myCircle(5.5, 6);
		Shape *myShape = &myCircle;
		myShape->area();
		myShape->area();
		//myShape->Shape::area(); //不可以呼叫基類的area()函式,錯誤
	}
	system("pause");
	return 0;
}

輸出結果為:

基類的建構函式被呼叫!
派生類的建構函式被呼叫!

圓的面積為:94.985
圓的周長為:34.54

派生類的解構函式被呼叫!
基類的解構函式被呼叫!

仔細觀察程式,和輸出結果。