纯虚函数和抽象类

来源:互联网 发布:软件的摊销年限 编辑:程序博客网 时间:2024/06/06 12:25

-------------------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()没有被实现的话同样无法实例化对象

virtualvoid 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()的事情则比较明确 "扫地"所以在这里将之实现

virtualvoid 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");

return0;

}

  

//纯虚函数:在虚函数表中其函数指针指向0是一个无意义的值

//即不需要实现也没有函数入口地址

//

//子类如果想要实例化则必须实现在父类中被定义为纯虚函数的函数

  

  

  

  

  

  

  

  

  

  

  

【made by siwuxie095】

0 0