/*这个实例是对一个典型例子的改写。在程序中使用虚函数和抽象基类。类的层次结构是抽象基类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++程序设计的大门。*/
分享到:
相关推荐
学生信息包括:学号、姓名、性别、年龄、班级等信息。 小学生除了包括学生所有信息外,还包括英语、数学和...设计一程序能够对学生成绩进行管理,应用到继承、抽象类、虚函数、虚基类、多态和文件的输入/输出等内容。
系统的介绍C++里面的虚函数与抽象类概念,并举例概述
建立一个学生基类sysustutent,有注册缴费reg(),选课select()等成员函数,派生出软件学院学生类ssstudent,管理学院学生类msstudent,以及从ssstudent和msstudent派生出的双学士学位类ddstudent。
某公司需要存储雇员的编号、姓名、级别和月薪,并显示全部信息。雇员分为经理、技术人员、销售人员和销售...设计一程序能够对公司人员进行管理,应用到继承、抽象类、虚函数、虚基类、多态和文件的输入/输出等内容。
(1)声明抽象基类及其派生类,设计类及其成员变量和成员函数,利用虚 函数实现对三种形状(如圆、正方形、三角形)的面积和周长的计算。在主函数 中可以调用类的成员函数,分别计算并输出三种形状的面积和周长。 ...
其中,Transition 是切屏的抽象基类,定义了屏幕切换期间发生的基本事务。虚函数主要包括:Init(初始化)、tearDown(销毁,切屏完成需要的清理过程)、handleTickEvent(Tick 事件处理函数,主要用于完成切屏的...
例如,虚函数就属此类情况。这时,派生类是抽象的基类的实现,即可看成是基类定义的延续。这也是派生类的一种常用方法。 派生类 在多继承时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。 派生...
应用多继承中虚拟基类的应用,掌握虚拟函数在多态性中的应用,掌握虚函数、纯虚函数、抽象类的概念,并能应用抽象类解决实际问题。
设计一程序能够对学生成绩进行管理,应用到继承、抽象类、虚函数、虚基类、多态和文件的输入/输出等内容。 2、功能要求 (1)添加功能:程序能够添加不同学生的记录,提供选择界面供用户选择所要添加的类别,要求学号...
设计一程序能够对学生成绩进行管理,应用到继承、抽象类、虚函数、虚基类、多态和文件的输入/输出等内容。 B.功能要求 (1)添加功能:程序能够添加不同学生的记录,提供选择界面供用户选择所要添加的类别,要求学号...
12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 ...
12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 ...
C4.3 回顾抽象基类 335 第12章 有序表及其实现 339 12.1 指定ADT有序表 340 12.1.1 ADT有序表的模板接口 342 12.1.2 使用有序表的操作 343 12.2 基于链表的实现 344 12.2.1 头文件 344 12.2.2 实现文件 345 ...
0032 成员函数的模板不可以是虚函数 12 0033 利用递归函数计算阶乘 12 0034 函数模板的应用 13 0035 使用指针数组 13 0036 函数指针数组的应用 13 0037 函数重载的注意事项 14 0038 使用typename关键字...
2.定义一个车(Vehicle)类,有run,stop等成员函数,由此派生出自行车(bicycle)类、汽车(car)类,由bicycle类和car类派生出摩托车(motocar)类,它们都包含run,stop等成员函数,编写相应的虚函数并测试。...
12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 ...
图 365 12.1 基本概念 365 12.2 应用 366 12.3 特性 368 12.4...虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394...
12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 ...
12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 ...
我们知道构造函数有一个必须遵守的规则,即构造函数不能定义为虚函数。但有一个具体的应用是要求是在不同的场景下通过一个指针或者引用生成不同的对象,这类似于类型的动态生成,即在执行期才能确定具体的对象。这...