纯虚函数 抽象类 虚析构函数

纯虚函数

基类中不能给出有意义的虚函数定义,这时可以把它声明成纯虚函数,把它的定义留给派生类来做。纯虚函数不需要实现。

定义纯虚函数

class 类名{
        virtual 返回值类型 函数名(参数表) = 0;
    };

抽象类

抽象类只能作为基类来使用。不能声明抽象类的对象。构造函数不能是虚函数,析构函数可以是虚函数。构造函数不能为虚函数,因为对象没有构造,无法形成虚函数表,即无法运行时多态。

若构造函数中存在虚函数,虚函数在构造函数中,已经失去了虚函数的动态绑定特性

  1. 抽象类不能用于直接创建对象实例,可以声明抽象类的指针和引用
  2. 可使用指向抽象类的指针支持运行时多态性
  3. 派生类中必须实现基类中的纯虚函数,否则它仍将被看作一个抽象类
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Shape
{
public:
    virtual void Draw() = 0;
    virtual ~Shape()
    {
        cout << "~Shape..." << endl;
    }
};

class Circle : public Shape
{
public:
    void Draw()
    {
        cout << "Circle::Draw() ..." << endl;
    }
    ~Circle()
    {
        cout << "~Circle ..." << endl;
    }
};

class Square : public Shape
{
public:
    void Draw()
    {
        cout << "Square::Draw() ..." << endl;
    }
    ~Square()
    {
        cout << "~Square ..." << endl;
    }
};

class Rectangle : public Shape
{
public:
    void Draw()
    {
        cout << "Rectangle::Draw() ..." << endl;
    }
    ~Rectangle()
    {
        cout << "~Rectangle ..." << endl;
    }
};

void DrawAllShapes(const vector<Shape *> &v)
{
    vector<Shape *>::const_iterator it;
    for (it = v.begin(); it != v.end(); ++it)
    {
        (*it)->Draw();
    }
}

void DeleteAllShapes(const vector<Shape *> &v)
{
    vector<Shape *>::const_iterator it;
    for (it = v.begin(); it != v.end(); ++it)
    {
        delete(*it);
    }
}

// 简单工厂模式
class ShapeFactory
{
public:
    static Shape *CreateShape(const string &name)
    {
        Shape *ps = 0;
        if (name == "Circle")
        {
            ps = new Circle;
        }
        else if (name == "Square")
        {
            ps = new Square;
        }
        else if (name == "Rectangle")
        {
            ps = new Rectangle;
        }

        return ps;
    }
};

int main(void)
{
    //Shape s;      //Error,不能实例化抽象类
    vector<Shape *> v;
    //Shape* ps;
    //ps = new Circle;
    //v.push_back(ps);
    //ps = new Square;
    //v.push_back(ps);
    //ps = new Rectangle;
    //v.push_back(ps);

    Shape *ps;
    ps = ShapeFactory::CreateShape("Circle");
    v.push_back(ps);
    ps = ShapeFactory::CreateShape("Square");
    v.push_back(ps);
    ps = ShapeFactory::CreateShape("Rectangle");
    v.push_back(ps);

    DrawAllShapes(v);
    DeleteAllShapes(v);


    return 0;
}

程序结果输出

Circle::Draw() ...
Square::Draw() ...
Rectangle::Draw() ...
~Circle ...
~Shape...
~Square ...
~Shape...
~Rectangle ...
~Shape...

虚析构函数

析构函数可以声明为虚函数,析构函数还可以是纯虚的

  1. delete基类指针,程序会根据基类指针指向的对象的类型确定要调用的析构函数
  2. 基类的析构函数为虚函数,所有派生类的析构函数都是虚函数
#include <iostream>
using namespace std;


// 对于一个没有任何接口的类,如果想要将它定义成抽象类,只能将虚析构函数声明为纯虚的
// 通常情况下在基类中纯虚函数不需要实现
// 例外是纯虚析构函数要给出实现。(给出一个空的实现即可)
class Base
{
public:
    virtual ~Base() = 0
    {

    }
};

class Derived : public Base
{

};

int main(void)
{
    //  Base b; //error, 抽象类
    Derived d;
    return 0;
}

通常情况下在基类中纯虚函数不需要实现,例外是纯虚析构函数要给出实现,给出一个空的实现即可。