虚函数和抽象基类的应用

来源:岁月联盟 编辑:猪蛋儿 时间:2011-11-25

 

<span style="font-size:24px;">/*这个实例是对一个典型例子的改写。在程序中使用虚函数和抽象基类。类的层次结构是抽象基类Shape(形状)。Point(点),Circle(圆),Cylinder(圆柱体)都是Shape类的直接派生类和间接派生类*/ 

 

 

//下面是一个完整的程序,为了便于阅读,分段插入了一些文字说明。  

 

程序如下: 

第(1)部分 

 

#include <iostream>  

using namespace std; 

//声明抽象基类Shape  

class 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类对象point  

Circle circle(2.4,1.2,5.6); 

//建立Circle类对象circle  

Cylinder cylinder(3.5,6.4,5.2,10.5); 

//建立Cylinder类对象cylinder  

point.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++程序设计的大门。*/ 

 

摘自 wwj的梦想之路

图片内容