C++ 接口是使用抽象类来实现的,接口描述了类的行为和功能,而不需要完成类的特定实现。且抽象类与数据抽象互不混淆, 如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类,数据抽象则是一个把实现细节与相关的接口分离开的概念。
如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类(ABC:Abstract class)。
纯虚函数通过在声明中使用 "= 0" 来指定, "= 0" 是告诉编译器,函数没有主体。如下所示:
class Shape
{
protected:int width;int height;
public:Shape( int a=0, int b=0){width = a;height = b;}virtual int area() = 0; // 纯虚函数
};
设计抽象类是为了给其他类提供一个可以继承的、适当的基类。
注意:抽象类不能实例化对象,它只能作为接口使用,如果试图实例化一个抽象类的对象,会导致编译错误。若一个抽象类的子类需要被实例化,则必须实现子类的虚函数,意味着 C++ 支持使用抽象类声明接口。如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导致编译错误。可用于实例化对象的类被称为具体类。
定义一个函数为虚函数,不代表函数为不被实现的函数,是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。目的是起到一个规范的作用,是为了实现一个接口,规范继承这个类的程序员必须实现这个函数。
在下面的实例中,抽象类Shape定义一个接口: getArea(),两个派生类Rectangle 和 Triangle 通过不同的算法来实现getArea():
#include <iostream>
using namespace std;class Shape
{
public:virtual int getArea() = 0; // 提供接口框架的纯虚函数getArea()Shape(int i = 0, int j = 0){width = i;height = j;}void setWidth(int w){width = w;}void setHeight(int h){height = h;}
protected: //注意,这里是protected类型int width;int height;
};class Rectangle : public Shape
{
public:int getArea(){return (width * height);}
};class Triangle : public Shape
{
public:int getArea(){return (width * height) / 2;}
};int main(void)
{Rectangle Rect; Triangle Tri;Rect.setWidth(5);Rect.setHeight(7);cout << "Total Rectangle area: " << Rect.getArea() << endl; Tri.setWidth(5);Tri.setHeight(7);cout << "Total Triangle area: " << Tri.getArea() << endl; return 0;
}
编译和执行上面的代码:
Total Rectangle area: 35
Total Triangle area: 17
补充:面向对象的系统可能会使用一个抽象基类,为所有的外部应用程序提供一个适当的、通用的、标准化的接口。然后,派生类通过继承抽象基类,就把所有类似的操作都继承下来。
外部应用程序提供的功能(即公有函数)在抽象基类中是以纯虚函数的形式存在的。这些纯虚函数在相应的派生类中被实现。这个架构也使得新的应用程序可以很容易地被添加到系统中,即使是在系统被定义之后依然可以如此。