1. 程式人生 > >純虛函數和抽象類

純虛函數和抽象類

程序 uri 文件 hit 每一個 實現 use ble png

-------------------siwuxie095

純虛函數

C++ 中,用 字來修飾虛函數,即 純虛函數

純虛函數沒有函數體,同時在定義時,函數名的後邊要加 =0

看如下實例:

技術分享

純虛函數在虛函數表中的實現:

技術分享

如果定義了一個 Shape 類,因為其中有虛函數和純虛函數,

所以 Shape 類一定有一個虛函數表,當然,也就會有一個

虛函數表指針

在虛函數表中,如果是一個普通虛函數,則對應的函數指針

就是一個有意義的值,如果是一個

純虛函數,則對應的函數

指針的值就是 0

抽象類

純虛函數一定是某個類的成員函數,包含純虛函數的類叫 抽象類

即便只含有一個純虛函數

技術分享

顯然,上面的 Shape 類就是一個抽象類,如果使用 Shape 類

實例化一個對象,當該對象想去調用純虛函數 calcPerimeter(),

該怎麽調用呢?顯然是沒法調用的

所以,對於抽象類來說,C++ 不允許它實例化對象

技術分享

如果強行從棧中 或 堆中實例化一個對象,就會報錯

技術分享

不僅如此,抽象類的子類也有可能是抽象類

技術分享

如下:

定義一個人類:Person,它是一個抽象類,因為人的概念太抽象了,

所以工作不知道要做什麽,就直接寫成純虛函數,打印信息也不知道

要打印什麽,就也寫成純虛函數

技術分享

當使用工人類 Worker 去繼承人類 Person 時,可以想象,對於工人

來說,工種也是非常多的,單憑一個工人,可以打印一些他的信息,

如:名字、工號等,但他的工作也沒有辦法清晰具體的描述出來,於

是將 work() 也定義成純虛函數

技術分享

此時,Worker 作為 Person 的子類,它也是一個抽象類

當明確了是什麽工種,如:清潔工

Dustman,它繼承了 Worker,

也是工人的一種

技術分享

對於抽象類來說,它無法去實例化對象,抽象類的子類只有把抽象類中

的所有純虛函數都做了實現,這個子類才可以實例化對象

程序:

Person.h:

#ifndef PERSON_H

#define PERSON_H

//註意:對於每一個 .h 文件,都加了宏定義

//這是為了 .h 文件的重復包含

#include <string>

using namespace std;

class Person

{

public:

Person(string name);

virtual ~Person();//虛析構函數

//Person類太過抽象 所以work()不知道該幹些什麽所以定義成純虛函數

//假如在子類中同名函數work()沒有被實現的話 同樣無法實例化對象

virtual void work() = 0;

private:

string m_strName;

};

//純虛函數 沒有函數體(即大括號以及函數的實現) 括號後加 =0

//有純虛函數的類是抽象類 抽象類無法實例化對象

//無論是從堆中還是棧中都無法實例化對象,抽象類的子類也有可能是抽象類(即繼承)

#endif

Person.cpp:

#include "Person.h"

Person::Person(string name)

{

m_strName = name;

}

Person::~Person()

{

}

Worker.h:

#ifndef WORKER_H

#define WORKER_H

#include "Person.h"

class Worker :public Person

{

public:

Worker(string name,int age);

virtual ~Worker();

//假如此時work()依然沒有被實現 那麽Worker類也是抽象類

//virtual void work();

//

//Worker類中work()工種太多 也不知道該幹些什麽

//所以依然定義為純虛函數 或者直接繼承父類的純虛函數

//virtual void work()=0;

private:

int m_iAge;

};

#endif

Worker.cpp:

#include "Worker.h"

#include <iostream>

using namespace std;

Worker::Worker(string name, int age) :Person(name)

{

m_iAge = age;

}

Worker::~Worker()

{

}

//void Worker::work()

//{

// cout << "Worker::work()" << endl;

//}

Dustman.h:

#ifndef DUSTMAN_H

#define DUSTMAN_H

#include "Worker.h"

class Dustman :public Worker

{

public:

Dustman(string name, int age);

virtual ~Dustman();

//這裏work()的事情則比較明確 "掃地" 所以在這裏將之實現

virtual void work();

};

#endif

Dustman.cpp:

#include "Dustman.h"

#include <iostream>

using namespace std;

Dustman::Dustman(string name, int age) :Worker(name, age)

{

}

Dustman::~Dustman()

{

}

void Dustman::work()

{

cout << "掃地" << endl;

}

main.cpp:

#include <stdlib.h>

#include "Dustman.h"

#include <iostream>

using namespace std;

//對於一個類來說,它如果含有純虛函數,那麽它就無法進行實例化

//

//無法進行實例化這件事,本身是個雙刃劍:

//1)對於一些抽象的類來說,往往不希望它能實例化,

//因為它實例化之後也沒什麽用

//2)對於一些具體的類來說,要求必須實現那些純虛函數,

//使它變成一個具有具體動作的函數,這樣的類往往也比較具體

//

//在實際編碼中,要具體情況具體分析

int main(void)

{

//Worker worker("zhangsan", 20);

Dustman dustman("lisi", 15);

system("pause");

return 0;

}

//純虛函數:在虛函數表中其函數指針指向0 是一個無意義的值

//即不需要實現 也沒有函數入口地址

//

//子類如果想要實例化 則必須實現在父類中被定義為純虛函數的函數

【made by siwuxie095】

純虛函數和抽象類