純虛函數和抽象類
-------------------siwuxie095
純虛函數
在 C++ 中,用 純 字來修飾虛函數,即 純虛函數
純虛函數沒有函數體,同時在定義時,函數名的後邊要加 =0
看如下實例:
純虛函數在虛函數表中的實現:
如果定義了一個 Shape 類,因為其中有虛函數和純虛函數,
所以 Shape 類一定有一個虛函數表,當然,也就會有一個
虛函數表指針
在虛函數表中,如果是一個普通虛函數,則對應的函數指針
就是一個有意義的值,如果是一個
指針的值就是 0
抽象類
純虛函數一定是某個類的成員函數,包含純虛函數的類叫 抽象類,
即便只含有一個純虛函數
顯然,上面的 Shape 類就是一個抽象類,如果使用 Shape 類
實例化一個對象,當該對象想去調用純虛函數 calcPerimeter(),
該怎麽調用呢?顯然是沒法調用的
所以,對於抽象類來說,C++ 不允許它實例化對象
如果強行從棧中 或 堆中實例化一個對象,就會報錯
不僅如此,抽象類的子類也有可能是抽象類
如下:
定義一個人類:Person,它是一個抽象類,因為人的概念太抽象了,
所以工作不知道要做什麽,就直接寫成純虛函數,打印信息也不知道
要打印什麽,就也寫成純虛函數
當使用工人類 Worker 去繼承人類 Person 時,可以想象,對於工人
來說,工種也是非常多的,單憑一個工人,可以打印一些他的信息,
如:名字、工號等,但他的工作也沒有辦法清晰具體的描述出來,於
是將 work() 也定義成純虛函數
此時,Worker 作為 Person 的子類,它也是一個抽象類
當明確了是什麽工種,如:清潔工
也是工人的一種
對於抽象類來說,它無法去實例化對象,抽象類的子類只有把抽象類中
的所有純虛函數都做了實現,這個子類才可以實例化對象
程序:
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】
純虛函數和抽象類