zoukankan      html  css  js  c++  java
  • 纯虚函数和抽象类

    -------------------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】

  • 相关阅读:
    20121025
    活到老学到老
    VS2012 正式版BUG太多
    JSP页面basePath路径问题
    这样的日子
    正确用JQ的AJAX加载XML并解析
    JSP中的5中转发方式
    C#编码规范
    jsp判断用户是否在线
    beging
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6809605.html
Copyright © 2011-2022 走看看