C++没有接口类,它通过使用纯虚函数来生成抽象类。抽象类可以作为接口的集合,实现了接口类的功能。
C++中含有纯虚函数的类叫做抽象类,顾名思义,它本身就是行为抽象的集合,因此它只描述了有这个行为,但是并未描述行为的具体做法,具体的做法在派生类中去实现,不同的派生类有不同的实现。
纯虚函数是虚函数的特殊表现,它的一般形式:
class 类名
{
virtual 函数返回值类型 函数名 (参数列表) = 0; //即,抽象类不去实现函数体
};
实际上C++允许抽象类实现函数体,但是做为抽象类的人应当遵循所有子类都有的行为才可以在抽象类中实现。否则这与抽象类的设计理念相违背。
抽象类不能被实例化,因为大多数时候的抽象类的纯虚函数都没有相应的实现。
由于基类的指针(引用)可以使用子类的函数,这样,我们通过抽象类的指针可以去调用派生类对象的函数。
下面是一段代码来展示抽象类和纯虚函数。
#include<iostream>
constexpr double PI = 3.1415926;
using std::endl;
using std::cout;
class Figure //抽象类
{
public:
//定义纯虚函数
virtual double getArea() const = 0 //获取面积
{
cout << "Hello World" << endl; //实际上C++允许我们在抽象类中实现纯虚函数的函数体
return 0;
}
virtual double getCircum() const = 0; //获取周长
};
class Rect : public Figure
{
public:
Rect(double a,double b);
virtual double getArea()const
{
Figure::getArea(); //由于抽象类不能实例化,只能这样在派生类中调用。不能在类外调用
return a * b;
}
virtual double getCircum()const
{
return 2 * (a + b);
}
private:
double a;
double b;
};
Rect::Rect(double a, double b)
{
this->a = a;
this->b = b;
}
class Triangle : public Figure
{
public:
Triangle(double a,double b,double c);
virtual double getArea()const
{
//利用海伦公式计算三角形面积
double p = (a + b + c) / 2;
double tmp = p * (p - a) * (p - b) * (p - c);
return pow(tmp, 0.5);
}
virtual double getCircum()const
{
return a + b + c;
}
private:
double a;
double b;
double c;
};
Triangle::Triangle(double a, double b, double c)
{
this->a = a;
this->b = b;
this->c = c;
}
class Circle : public Figure
{
public:
Circle(double r);
virtual double getArea()const
{
return PI * r * r;
}
virtual double getCircum()const
{
return 2 * PI * r;
}
private:
double r;
};
Circle::Circle(double r)
{
this->r = r;
}
int main()
{
//Figure f; ---->error,抽象类不能实例化对象。
Figure* p_rect = new Rect(4, 6);
Figure* p_triangle = new Triangle(3, 3, 3);
Figure* p_circle = new Circle(10);
cout << "矩形面积:" << p_rect->getArea() << " 矩形周长:" << p_rect->getCircum() << endl;
cout << "三角形面积:" << p_triangle->getArea() << " 三角形周长:" << p_triangle->getCircum() << endl;
cout << "圆形面积:" << p_circle->getArea() << " 圆形周长:" << p_circle->getCircum() << endl;
return 0;
}
运行结果如下:
通过多态,基类指针可以访问子类的函数。