题目:编程定义抽象类Shape,由它派生出5个派生类Circle(圆形),Square(正方形),Rectangle(矩形),Trapezoid(梯形),Triangle(三角形)。用虚函数分别计算几种图形的面积,并求他们的和。要求:用基类指针数组,使它每一个元素指向一个派生类对象。
首先,我们来通俗了解一下什么是抽象类,
包含有纯虚函数的类是抽象类
什么又是纯虚函数,在之前的文章我们说过了虚函数,有时在基类中将某一成员函数声明为虚函数,并不是类本身的要求,而是考虑到派生类的需要,在基类中可以只声明一个函数名,具体的功能留给派生类根据需要去实现。
在这这种虚函数只需要在基类中说明函数原型,用来定义继承体系中的同意接口形式,然后在派生类的虚函数中重新定义具体实现代码,这种基类中的虚函数就是纯虚函数,其声明形式为:
virtual 函数类型 函数名(参数表)=0;
关于纯虚函数,有以下几点需要说明:
- 纯虚函数没有函数体;
- 最后面的"=0"并不表示函数返回值为0,只是形式上的作用,告诉编译系统这是一个纯虚函数。
- 这本质上是一个声明语句,所以最后有分号结束。
- 纯虚函数只有函数名而不具备函数的功能,不能被调用,它只是通知编译器合理声明了一个纯虚函数,留待在派生类中实现。因此,只有在派生类中定义之后,它才能更具备函数的功能,可以被调用。
- 如果在一个类中声明了纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数。
而抽象类呢:
1、上面说包含有纯虚函数的类为抽象类。由于抽象类常用做基类,通常称为抽象基类。
2、抽象类的主要作用是,通过它为一个类族(即其派生类等)建立一个公共的接口,使它能更有效地发挥其多态特性。
3、抽象类只负责声明这个接口,而接口的实现,即纯虚函数的函数体,要由派生类自己定义。
4、抽象类派生出新的类之后,如果派生类给出其纯虚函数的实现,这个派生类此时便可以定义自己的对象,从而不再是抽象类,否则,这个派生类仍然是一个抽象类。
5、抽象类不能实例化,即不能定义一个抽象类的对象,但是可以声明其指针和引用,通过这个指针或引用,就可以指向访问派生类对象。
此时,我们再来看这道题,首先创建一个抽象基类:
class Shape{ //定义抽象基类Shape
public:
virtual double Area() = 0; //求面积函数,声明为纯虚函数
};
没有别的要求,我们直接来进行派生它的五个子类,分别是:
//圆形派生类Circle
class Circle :public Shape{ //圆形派生类Circle
public:
Circle(double r) :radius(r){}
double Area(){
return 3.14*radius*radius;
}
private:
double radius; //圆半径
};
//正方形派生类Square
class Square :public Shape{
public:
Square(double r) :Sradius(r){}
double Area(){
return Sradius*Sradius;
}
private:
double Sradius; //正方形边长
};
//矩形派生类Rectangle
class Rectangle :public Shape{
public:
Rectangle(double w, double h) :Sweight(w), Shigh(h){}
double Area(){
return Sweight*Shigh;
}
protected:
double Sweight, Shigh; //矩形宽和高
};
//梯形派生类Trapezoid
class Trapezoid :public Shape{
public:
Trapezoid(double Swid, double Lwid, double Rhi) :Swidth(Swid), Lwidth(Lwid), Rhigh(Rhi){} //构造:梯形上底下底和高
double Area(){
return 0.5*(Swidth+Lwidth)*Rhigh;
}
protected:
double Swidth, Lwidth, Rhigh; //梯形上下底和高
};
//三角形派生类Triangle
class Triangle :public Shape{
public:
Triangle(double w,double h):width(w),height(h){}
double Area(){
return 0.5*width*height;
}
protected:
double width, height;
};
加上主测试函数,完整代码如下:
//编程定义抽象类Shape,由它派生出5个派生类Circle(圆形),Square(正方形),Rectangle(矩形),Trapezoid(梯形),Triangle(三角形)。
//用虚函数分别计算几种图形的面积,并求他们的和。要求:用基类指针数组,使它每一个元素指向一个派生类对象。
#include<iostream>
using namespace std;
class Shape{ //定义抽象基类
public:
virtual double Area() = 0; //求面积函数,声明为虚函数
};
class Circle :public Shape{ //圆形派生类Circle
public:
Circle(double r) :radius(r){}
double Area(){
return 3.14*radius*radius;
}
private:
double radius;
};
//正方形派生类Square
class Square :public Shape{
public:
Square(double r) :Sradius(r){}
double Area(){
return Sradius*Sradius;
}
private:
double Sradius;
};
//矩形派生类Rectangle
class Rectangle :public Shape{
public:
Rectangle(double w, double h) :Sweight(w), Shigh(h){} //构造:矩形宽和高
double Area(){
return Sweight*Shigh;
}
protected:
double Sweight, Shigh;
};
//梯形派生类Trapezoid
class Trapezoid :public Shape{
public:
Trapezoid(double Swid, double Lwid, double Rhi) :Swidth(Swid), Lwidth(Lwid), Rhigh(Rhi){} //构造:梯形上底下底和高
double Area(){
return 0.5*(Swidth+Lwidth)*Rhigh;
}
protected:
double Swidth, Lwidth, Rhigh;
};
//三角形派生类Triangle
class Triangle :public Shape{
public:
Triangle(double w,double h):width(w),height(h){}
double Area(){
return 0.5*width*height;
}
protected:
double width, height;
};
int main(){
Shape *s[6]; //声明一个基类指针数组
s[1] = new Circle(2);
s[2] = new Square(3);
s[3] = new Rectangle(3, 4);
s[4] = new Trapezoid(2, 3, 4);
s[5] = new Triangle(4, 5);
cout << "圆的面积为:" << s[1]->Area() << endl;
cout << "正方形的面积为:" << s[2]->Area() << endl;
cout << "矩形面积为:" << s[3]->Area() << endl;
cout << "梯形面积为:" << s[4]->Area() << endl;
cout << "三角形面积为:" << s[5]->Area() << endl;
cout << "总面积为:" << s[1]->Area() + s[2]->Area() + s[3]->Area() + s[4]->Area() + s[5]->Area() << endl;
return 0;
}
运行结果如下: