C++ 虚函数

虚函数是实现多态特性的重要工具. 下面看一个例子体会一下:

class base {
  public:
    virtual void show() { std::cout << "base" << std::endl; };
    virtual ~base() { std::cout << "base destruct" << std::endl; }
};

class derive : public base {
  public:
    void show() { std::cout << "derive" << std::endl; };
    ~derive() { std::cout << "derive destruct" << std::endl; }
};

int main(void) {
    derive der;
    base *d = &der;
    d->show();
    std::cout << "exit" << std::endl;
}

输出:

derive
exit
derive destruct
base destruct

通过基类的指针指向派生类的地址, 在调用基类对象时, 动态选择其真实类型关联的函数, 从而实现多态特性.

  • 构造函数为什么不能是虚函数?
    虚函数的主要目的是通过基类的指针或引用, 调用派生类关联的函数, 实现多态特性. 而构造函数是在初始化一个对象时调用的, 派生类此时并没有完全构造出来(调用构造函数前), 也没有与对应的基类指针或引用关联起来, 没有办法使用多态特性. 构造函数是虚函数没有必要.
  • 虚构函数为什么可以是虚函数?
    因为释放堆上内存时可能通过基类的指针进行delete, 如果析构函数不是虚函数, 则会调用基类的析构函数, 派生类就得不到正确的销毁, 造成内存泄露. 一般在使用多态特性时, 基类的析构函数都应是虚函数.
  • 虚函数的默认参数是静态绑定的. 即, 通过基类的指针访问派生类时, 传入的是基类的默认参数, 而不是派生类的默认参数.
  • 虚函数可以是私有的, 只要在动态绑定时能绑定即可. 例如: 基类的虚函数是私有的, 派生类的虚函数是公有的, 则通过基类的指针或引用访问派生类的方法时, 并不会存在找不到函数的错误.

纯虚函数

纯虚函数简单来说就是没有定义虚函数. 写法就是在虚函数后添加= 0修饰. 下面看一个例子:

class base {
  public:
    virtual void show() = 0;
    virtual ~base() { std::cout << "base destruct" << std::endl; }
};

class derive : public base {
  public:
    void show() { std::cout << "derive" << std::endl; };
    ~derive() { std::cout << "derive destruct" << std::endl; }
};

int main(void) {
    derive der;
    base *d = &der;
    d->show();
    std::cout << "exit" << std::endl;
}

纯虚函数有什么用呢? 纯虚函数一般用于实现抽象类. 那什么是抽象类呢? 抽象类简单来说就是接口, 通过定义一些共同行为的集合, 对派生类进行约束. 当然抽象类也可以有数据成员. 那抽象类有什么特点呢?

  • 抽象类不能实例化, 一般使用指针或引用实现多态特性.
  • 只要有一个纯虚函数 , 该类就是抽象类.
  • 抽象类的所有虚函数(析构函数除外), 必须在派生类中实现, 才能成为非抽象类 , 否则派生类也是抽象类.
  • 抽象类可以有构造函数. 抽象类的构造函数一般被派生类调用, 初始化抽象类的数据成员.

如果觉得有帮助,可以扫描右边的微信打赏码支持一下.

Leave a Reply

Your email address will not be published. Required fields are marked *