c++中抽象類

 在介紹抽象類之前,我們先介紹一下純虛函數。

1.純虛函數

  在基類中僅僅給出聲明,不對虛函數實現定義,而是在派生類中實現。這個虛函數稱爲純虛函數。普通函數如果僅僅給出它的聲明而沒有實現它的函數體,這是編譯不過的。純虛函數沒有函數體。

  純虛函數需要在聲明之後加個=0

class <基類名>

{

virtual <類型><函數名>(<參數表>)=0; ......

};

2.抽象類

  含有純虛函數的類被稱爲抽象類。抽象類只能作爲派生類的基類,不能定義對象,但可以定義指針。在派生類實現該純虛函數後,定義抽象類對象的指針,並指向或引用子類對象。

1)在定義純虛函數時,不能定義虛函數的實現部分;

2)在沒有重新定義這種純虛函數之前,是不能調用這種函數的。

  抽象類的唯一用途是爲派生類提供基類,純虛函數的作用是作爲派生類中的成員函數的基礎,並實現動態多態性。繼承於抽象類的派生類如果不能實現基類中所有的純虛函數,那麼這個派生類也就成了抽象類。因爲它繼承了基類的抽象函數,只要含有純虛函數的類就是抽象類。純虛函數已經在抽象類中定義了這個方法的聲明,其它類中只能按照這個接口去實現。

3.接口和抽象類的區別

1C++中我們一般說的接口,表示對外提供的方法,提供給外部調用。是溝通外部跟內部的橋樑。也是以類的形式提供的,但一般該類只具有成員函數,不具有數據成員;

2)抽象類可以既包含數據成員又包含方法。

抽象類的實例

1.抽象類IShape作爲基類:只有頭文件,沒有實現文件

#ifndef SHAPE_H

#define SHAPE_H

#include

using std::string;

//interface

class IShape

{

public:

virtual float getArea()=0; //純虛函數,獲得面積

virtual string getName()=0; //純虛函數,返回圖形的名稱

};

#endif

2.派生類Circle類繼承自抽象類IShape

Circle.h頭文件:

#ifndef CIRCLE_H

#define CIRCLE_H

#include"Shape.h"

class CCircle : public IShape //公有繼承自IShape

{

public:

CCircle(float radius); //構造函數

public:

virtual float getArea(); //實現聲明實現兩個基類的函數,聲明的時候需要加virtual關鍵字,實現的時候就不需要加virtual關鍵字了。

virtual string getName();

private:

float m_fRadius; //派生類可以擁有自己的成員

};

#endif

Circle.cpp實現文件:

#include"Circle.h"

CCircle::CCircle(float radius)

:m_fRadius(radius) //使用構造函數的初始化列表初始化

{

}

float CCircle::getArea() / /實現實現兩個基類的函數

virtual string getName();

{

return 3.14 * m_fRadius * m_fRadius;

}

string CCircle::getName()

{

return "CCircle";

}

3. 派生類Rect類繼承自抽象類IShape

Rect.h頭文件:

#ifndef RECT_H

#define RECT_H

#include"shape.h"

class CRect : public IShape

{

public:

CRect(float nWidth, float nHeight);

public:

virtual float getArea();

virtual string getName();

private:

float m_fWidth; //矩形類具有自己的兩個屬性,寬和高

float m_fHeight;

};

Rect.cpp實現文件:

#include"Rect.h"

CRect::CRect(float fWidth, float fHeight)

:m_fWidth(fWidth), m_fHeight(fHeight)

{

}

float CRect::getArea()

{

return m_fWidth * m_fHeight;

}

string CRect::getName()

{

return "CRect";

}

4.測試文件main.cpp

#include

#include"Rect.h"

#include"Circle.h"

using namespace std;

int main()

{

IShape* pShape = NULL; //定義了一個抽象類的指針,注意抽象類不能定義對象但是可以定義指針

pShape = new CCircle(20.2); //基類指針指向派生類的對象

cout<getName()<<" "<getArea()<<endl;

delete pShape; //釋放了CCirle對象所佔的內存,但是指針是沒有消失的,它現在就是一個野指針,我們在使用之前必須對它賦值

pShape = new CRect(20, 10); //基類指針指向派生類的對象

cout<getName()<<" "<getArea()<<endl;

return 0;

}

  運行結果如下:可以看到,我們使用父類的指針調用同一個函數,分別調用了這兩個派生類的對應函數,它根據指針指向的類型的不同來決定調用的方法。即使我們以後需要新增加幾個類,我們還是這種調用方法,這就是多態的巨大魅力。

 



發佈了11 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章