程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++基礎知識 >> C++純虛函數和抽象類

C++純虛函數和抽象類

編輯:C++基礎知識
在C++中,可以將虛函數聲明為純虛函數,語法格式為:

virtual 返回值類型 函數名 (函數參數) = 0;

純虛函數沒有函數體,只有函數聲明,在虛函數聲明的結尾加上=0,表明此函數為純虛函數。
最後的=0並不表示函數返回值為0,它只起形式上的作用,告訴編譯系統“這是純虛函數”。
包含純虛函數的類稱為抽象類(Abstract Class)。之所以說它抽象,是因為它無法實例化,也就是無法創建對象。原因很明顯,純虛函數沒有函數體,不是完整的函數,無法調用,也無法為其分配內存空間。

抽象類通常是作為基類,讓派生類去實現純虛函數。派生類必須實現純虛函數才能被實例化。

純虛函數使用舉例:
#include <iostream>
using namespace std;

//線
class Line{
public:
    Line(float len);
    virtual float area() = 0;
    virtual float volume() = 0;
protected:
    float m_len;
};
Line::Line(float len): m_len(len){ }

//矩形
class Rec: public Line{
public:
    Rec(float len, float width);
    float area();
protected:
    float m_width;
};
Rec::Rec(float len, float width): Line(len), m_width(width){ }
float Rec::area(){ return m_len * m_width; }

//長方體
class Cuboid: public Rec{
public:
    Cuboid(float len, float width, float height);
    float area();
    float volume();
protected:
    float m_height;
};
Cuboid::Cuboid(float len, float width, float height): Rec(len, width), m_height(height){ }
float Cuboid::area(){ return 2 * ( m_len*m_width + m_len*m_height + m_width*m_height); }
float Cuboid::volume(){ return m_len * m_width * m_height; }

//正方體
class Cube: public Cuboid{
public:
    Cube(float len);
    float area();
    float volume();
};
Cube::Cube(float len): Cuboid(len, len, len){ }
float Cube::area(){ return 6 * m_len * m_len; }
float Cube::volume(){ return m_len * m_len * m_len; }

int main(){
    Line *p = new Cuboid(10, 20, 30);
    cout<<"The area of Cuboid is "<<p->area()<<endl;
    cout<<"The volume of Cuboid is "<<p->volume()<<endl;
  
    p = new Cube(15);
    cout<<"The area of Cube is "<<p->area()<<endl;
    cout<<"The volume of Cube is "<<p->volume()<<endl;

    return 0;
}
運行結果:
The area of Cuboid is 2200
The volume of Cuboid is 6000
The area of Cube is 1350
The volume of Cube is 3375

本例中定義了四個類,它們的繼承關系為:Line --> Rec --> Cuboid --> Cube。

Line 是一個抽象類,也是最頂層的基類,在 Line 類中定義了兩個純虛函數 area() 和 volume()。

在 Rec 類中,實現了 area() 函數;所謂實現,就是定義了純虛函數的函數體。但這時 Rec 仍不能被實例化,因為它沒有實現繼承來的 volume() 函數,volume() 仍然是純虛函數,所以 Rec 也仍然是抽象類。

直到 Cuboid 類,才實現了 volume() 函數,才是一個完整的類,才可以被實例化。

可以發現,Line 類表示“線”,沒有面積和體積,但它仍然定義了 area() 和 volume() 兩個純虛函數。這樣的用意很明顯:Line 類不需要被實例化,但是它為派生類提供了“約束條件”,派生類必須要實現這兩個函數,完成計算面積和體積的功能,否則就不能實例化。

在實際開發中,你可以定義一個抽象基類,只完成部分功能,未完成的功能交給派生類去實現(誰派生誰實現)。這部分未完成的功能,往往是基類不需要的,或者在基類中無法實現的。雖然抽象基類沒有完成,但是卻強制要求派生類完成,這就是抽象基類的“霸王條款”。

抽象基類除了約束派生類的功能,還可以實現多態。請注意第 51 行代碼,指針 p 的類型是 Line,但是它卻可以訪問派生類中的 area() 和 volume() 函數,正是由於在 Line 類中將這兩個函數定義為純虛函數;如果不這樣做,51 行後面的代碼都是錯誤的。我想,這或許才是C++提供純虛函數的主要目的。

關於純虛函數的幾點說明

1) 一個純虛函數就可以使類成為抽象基類,但是抽象基類中除了包含純虛函數外,還可以包含其它的成員函數(虛函數或普通函數)和成員變量。

2) 只有類中的虛函數才能被聲明為純虛函數,普通成員函數和頂層函數均不能聲明為純虛函數。如下例所示:
//頂層函數不能被聲明為純虛函數
void fun() = 0;   //compile error

class base{
public :
    //普通成員函數不能被聲明為純虛函數
    void display() = 0;  //compile error
};
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved