1、纯虚拟函数
强制子类实现接口
C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。
C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。
C++中的纯虚函数也是一种“运行时多态”。
如下面的类包含纯虚函数,就是“抽象类”:
2、非纯虚拟函数(impure virtual)
允许子类重写
声明一般(非纯)虚拟函数的目的是让派生类继承函数的接口和缺省行为。
C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。
子类可以重写父类的虚函数实现子类的特殊化。
有时,我们希望基类提供的缺省行为只能被派生类“显式”的继承,即在派生类不重新定义函数的时候,不继承缺省行为。两种方法:
1.将基类函数声明为纯虚拟函数,将缺省行为声明为protected非虚拟函数,则派生类必须重新声明他,并且可以在函数中使用表示缺省行为的函数。此时,函数的接口与缺省行为用不同的函数表示,会有一些雷同名称的函数。
2.将基类函数声明为纯虚拟函数,并为其提供一个定义,派生类中必须声明函数,若不提供定义,则继承基类的定义作为缺省行为。此时,将缺省行为也置于public中。
3、非虚拟函数
子类必须继承
声明非虚拟函数的目的是让派生类继承函数的接口和实现。
因此,不要将所有函数都声明为非虚拟函数,除非他确实不会作为基类。通常也不要将成员函数都声明为虚拟函数,尤其是函数不需要再派生类中重新定义时。
继承接口和实现, 主要包含三种方式:
1. 只继承接口, 纯虚函数;
2. 继承接口和实现, 允许覆写(override), 虚函数;
3. 继承接口和实现, 不允许覆写(override), 非虚函数;
1. 纯虚函数:
只继承接口, 但是派生类必须实现其接口;
纯虚函数也可以包含实现, 但是只能在指明类(即, class::)的时候使用
2. 虚函数:
继承接口和实现, 派生类可以覆写(override), 也可以使用默认版本, 即基函数(base)版本;
纯虚函数约束程序更多, 虚函数更灵活;
3. 非虚函数
继承接口和实现, 强制的提供派生类的实现, 不可以改变, 即不可以覆写(override);
关于派生类使用纯虚函数的实现, 如下:
/*************************************************
File: pure_virtual.cpp
Copyright: C.L.Wang
Author: C.L.Wang
Date: 2014-04-01
Description: explicit
Email: morndragon@126.com
**************************************************/
/*eclipse cdt, gcc 4.8.1*/
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() const;
virtual void error (const std::string& msg) {std::cout << msg << std::endl;};
int objectID() const { return 1;};
};
void Shape::draw() const {
std::cout << "Shape Draw!" << std::endl;
}
class Rectangle: public Shape {
public:
void draw() const {std::cout << "Rect Draw!" << std::endl;};
};
class Ellipse: public Shape {
public:
void draw() const {std::cout << "Elli Draw!" << std::endl;};
};
int main () {
Shape* ps1 = new Rectangle;
Shape* ps2 = new Ellipse;
ps1->draw();
ps2->draw();
std::cout << "Attention: " << std::endl;
ps1->Shape::draw();
ps2->Shape::draw();
return 0;
}
虚函数(简朴的impure virtual函数)背后的故事和纯虚函数(pure virtual函数)有点不同,一如往常,派生类继承其函数接口,但虚函数(简朴的impure virtual函数)会提供一份实现代码,派生类可能覆写(override)它,所以结论是:
1、声明虚函数(简朴的impure virtual函数)的目的是让派生类继承该函数的接口和缺省实现,考虑error函数,其接口表示,每个类都必须支持一个“当遇上错误是可调用”的函数,但每个类可自由处理错误,若某个类不想针对错误做出任何特殊行为,它可以退回到Shape类提供的缺省错误处理行为。
但是允许虚函数(简朴的impure virtual函数)同时指定函数声明和函数缺省行为,却有可能造成危险