虚函数和抽象基类的应用

来源:互联网 发布:潮流计算的软件 编辑:程序博客网 时间:2024/04/29 05:24
/*这个实例是对一个典型例子的改写。在程序中使用虚函数和抽象基类。类的层次结构是抽象基类Shape(形状)。Point(点),Circle(圆),Cylinder(圆柱体)都是Shape类的直接派生类和间接派生类*///下面是一个完整的程序,为了便于阅读,分段插入了一些文字说明。程序如下:第(1)部分#include <iostream>using namespace std;//声明抽象基类Shapeclass Shape{public:virtual float area( )const {return 0.0;}//虚函数virtual float volume()const {return 0.0;}//虚函数virtual void shapeName()const =0;//纯虚函数};第(2)部分//声明Point类class Point:public Shape//Point是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::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 &p){     output<<″[″<<p.x<<″,″<<p.y<<″]″;return output;}第(3)部分//声明Circle类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::Circle(float a,float b,float r):Point(a,b),radius(r){}void Circle::setRadius(float r):radius(r){}float Circle::getRadius( )const {return radius;}float Circle::area( )const {return 3.14159*radius*radius;}ostream &operator <<(ostream &output,const Circle &c){output<<″[″<<c.x<<″,″<<c.y<<″], r=″<<c.radius;return output;}第(4)部分//声明Cylinder类class Cylinder:public Circle{public:Cylinder (float x=0,float y=0,float r=0,float h=0);void setHeight(float );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::Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h){}void Cylinder::setHeight(float h){height=h;}float Cylinder::area( )const{return 2*Circle::area( )+2*3.14159*radius*height;}float Cylinder::volume( )const{return Circle::area( )*height;}ostream &operator <<(ostream &output,const Cylinder& cy){     output<<″[″<<cy.x<<″,″<<cy.y<<″], r=″<<cy.radius<<″, h=″<<cy.height; return output;}第(5)部分//main函数int main( ){Point point(3.2,4.5);//建立Point类对象pointCircle circle(2.4,1.2,5.6);//建立Circle类对象circleCylinder cylinder(3.5,6.4,5.2,10.5);//建立Cylinder类对象cylinderpoint.shapeName();//静态关联cout<<point<<endl;circle.shapeName();//静态关联cout<<circle<<endl;cylinder.shapeName();//静态关联cout<<cylinder<<endl<<endl;Shape *pt;//定义基类指针pt=&point;//指针指向Point类对象pt->shapeName( );//动态关联cout<<″x=″<<point.getX( )<<″,y=″<<point.getY( )<<″\\narea=″<<pt->area( )<<″\\nvolume=″<<pt->volume()<<″\\n\\n″;pt=&circle;//指针指向Circle类对象pt->shapeName( );//动态关联cout<<″x=″<<circle.getX( )<<″,y=″<<circle.getY( )<<″\\narea=″<<pt->area( )<<″\\nvolume=″<<pt->volume( )<<″\\n\\n″;pt=&cylinder;//指针指向Cylinder类对象pt->shapeName( );//动态关联cout<<″x=″<<cylinder.getX( )<<″,y=″<<cylinder.getY( )<<″\\narea=″<<pt->area( )<<″\\nvolume=″<<pt->volume( )<<″\\n\\n″;return 0;}程序运行结果如下。请读者对照程序分析。Point:[3.2,4.5](Point类对象point的数据:点的坐标)Circle:[2.4,1.2], r=5.6 (Circle类对象circle的数据:圆心和半径)Cylinder:[3.5,6.4], r=5.5, h=10.5 (Cylinder类对象cylinder的数据: 圆心、半径和高)Point:x=3.2,y=4.5 (输出Point类对象point的数据:点的坐标)area=0 (点的面积)volume=0 (点的体积)Circle:x=2.4,y=1.2 (输出Circle类对象circle的数据:圆心坐标)area=98.5203 (圆的面积)volume=0 (圆的体积)Cylinder:x=3.5,y=6.4 (输出Cylinder类对象cylinder的数据:圆心坐标)area=512.595 (圆的面积)volume=891.96 (圆柱的体积)从本例可以进一步明确以下结论:/*(1)一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象。(2)抽象基类与普通基类不同,它一般并不是现实存在的对象的抽象(例如圆形(Circle)就是千千万万个实际的圆的抽象),它可以没有任何物理上的或其他实际意义方面的含义。(3)在类的层次结构中,顶层或最上面的几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。(4)抽象基类是本类族的公共接口。或者说,从同一基类派生出的多个类有同一接口。(5)区别静态关联和动态关联。(6)如果在基类声明了虚函数,则在派生类中凡是与该函数有相同的函数名、函数类型、参数个数和类型的函数,均为虚函数(不论在派生类中是否用virtual声明)。(7)使用虚函数提高了程序的可扩充性。把类的声明与类的使用分离。这对于设计类库的软件开发商来说尤为重要。开发商设计了各种各样的类,但不向用户提供源代码,用户可以不知道类是怎样声明的,但是可以使用这些类来派生出自己的类。利用虚函数和多态性,程序员的注意力集中在处理普遍性,而让执行环境处理特殊性。多态性把操作的细节留给类的设计者(他们多为专业人员)去完成,而让程序人员(类的使用者)只需要做一些宏观性的工作,告诉系统做什么,而不必考虑怎么做,极大地简化了应用程序的编码工作,大大减轻了程序员的负担,也降低了学习和使用C++编程的难度,使更多的人能更快地进入C++程序设计的大门。*/