一个C++的多态和虚函数实例
类的说明:
code:
#include<iostream> #include<string> #define PAI 3.1415926 using namespace std; class Shape //抽象类 { public: virtual float area() const //计算面积 { return 0.0; } virtual float volume() const//计算体积 { return 0.0; } virtual void ShapeName() const =0;//纯虚函数 ——形状名 }; //声明点类 class Point: public Shape { public: Point(float =0,float =0); void setPoint(float,float); float getX()const {return x;} float getY()const {return y;} virtual void ShapeName()const { cout<<"Point:"; } friend ostream &operator<< (ostream &,const Point &); protected: float x,y; }; //对点类的函数进行类外定义 Point::Point(float a,float b) { x=a; y=b; } void Point::setPoint(float a,float b) { x=a; y=b; } ostream &operator<<(ostream &output,const Point&b) { output<<"["<<b.x<<","<<b.y<<"]"<<endl; return output; } //声明圈类 class Circle:public Point { public: Circle(float x=0,float y=0,float r=0); void setRadius(float); float GetRadius()const; virtual float area() const; virtual void ShapeName()const { cout<<"Circle:"; } friend ostream &operator<< (ostream &,const Circle &); protected: float radius; }; //对圈内的函数进行类外定义 Circle::Circle(float x,float y,float r):Point(x,y),radius(r){} void Circle::setRadius(float r) { radius=r; } float Circle::GetRadius()const { return radius; } float Circle::area()const { return PAI*radius*radius; } ostream &operator<<(ostream &output,const Circle &c) { output<<"["<<c.x<<","<<c.y<<"],r="<<c.radius<<endl; return output; } //声明圆柱类 class Cylinder:public Circle { public: Cylinder(float x=0,float y=0,float r=0,float h=0); void setHeight(float h); virtual float area()const; virtual float volume()const; virtual void ShapeName()const { cout<<"Cylinder:"; } friend ostream &operator<< (ostream &,const Cylinder&); protected: float height; }; //对圆柱类中的函数进行类外定义 Cylinder::Cylinder(float x,float y,float r,float h) :Circle(x,y,r),height(h){}//对于多层继承,只需要给其直接基类传值 void Cylinder::setHeight(float h) { height=h; } float Cylinder::area()const { return PAI*radius*radius; } float Cylinder::volume()const { return PAI*radius*radius*height; } ostream &operator <<(ostream &output,const Cylinder&c) { output<<"["<<c.x<<","<<c.y<<"],r="<<c.radius<<",h="<<c.height<<endl; return output; } int main() { Point point(3.2,4.5); Circle circle(2.4,1.2,5.6); Cylinder cylinder(3.5,6.4,5.2,10.5); point.ShapeName(); //静态关联 cout<<point<<endl; circle.ShapeName(); //静态关联 cout<<circle<<endl; cylinder.ShapeName(); //静态关联 cout<<cylinder<<endl; Shape *pt; //定义基类指针pt pt=&point; //指针指向point pt->ShapeName(); //动态关联 cout<<"x="<<point.getX()<<",y="<<point.getY()<<"\narea="<<pt->area() <<"\nvolume="<<pt->volume()<<endl<<endl; pt=&circle; //指针指向Circle pt->ShapeName(); //动态关联 cout<<"x="<<circle.getX()<<",y="<<circle.getY()<<"\narea="<<pt->area() <<"\nvolume="<<pt->volume()<<endl<<endl; pt=&cylinder; //指针指向cylinder pt->ShapeName(); //动态关联 cout<<"x="<<cylinder.getX()<<",y="<<cylinder.getY()<<"\narea="<<pt->area() <<"\nvolume="<<pt->volume()<<endl<<endl; cout<<endl; return 0; }
Shape是图形类,它是所有图形的一个概述,抽象了图形的名称,面积,体积函数,并定义为虚函数。因为每一个图形都应该有个名字,所以声明ShapeName函数为纯虚函数,而面积和体积等特性并不一定是每一个图形都具有的特征,所以默认置零。
Point类继承自Shape,它定义了纯虚函数ShapeName,然后添加了自己的setPoint,getX,getY成员函数,并重载了输出流运算符用于Point类的输出。
Circle类继承自Point,它定义了纯虚函数ShapeName,以及虚函数area,然后添加了自己的setRadius,getRadius成员函数,并重载了输出流运算符用于Circle类的输出。
Cylinder类继承自Circle,它定义了纯虚函数ShapeName,以及虚函数area,和volume,然后添加了自己的setHeight成员函数,并重载了输出流运算符用于Cylinder的输出。
区别静态关联和动态关联:
如果是通过对象名调用虚函数(如point.ShapeName()),在编译阶段就能确定调用的是那一个类的虚函数,所以属于静态关联。
如果是通过基类指针调用虚函数(如pt->volume()),在编译阶段无法从语句本身确定是那一个类的虚函数,只有在运行时,pt指向某一类对象后,才能确定调用的是那一个类的虚函数,故为动态关联。