分类: C/C++
2013-08-15 11:12:46
}
程序编译通过,运行结果为
x=3.5,y=6.4
p(new):[8.5,6.8]
测试程序检查了基类中各函数的功能,以及运算符重载的作用,证明程序是正确的。
(2)声明派生类Circle在上面的基础上,再写出声明派生类Circle的部分:
class Circle:public Point//circle是Point类的公用派生类
{
public:
Circle(float x=0,float y=0,float r=0);//构造函数
void setRadius(float );//设置半径值
float getRadius( )const;//读取半径值
float area ( )const;//计算圆面积
friend ostream &operator <<(ostream &,const Circle &);//重载运算符“<<”
private:
float radius;
};
//定义构造函数,对圆心坐标和半径初始化
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<<″Center=[″<
return output;
}
为了测试以上Circle类的定义,可以写出下面的主函数:
int main( )
{
Circle c(3.5,6.4,5.2);//建立Circle类对象c,并给定圆心坐标和半径
cout<<″original circle:\\nx=″<
c.setRadius(7.5);//设置半径值
c.setPoint(5,5);//设置圆心坐标值x,y
cout<<″new circle:\\n"<
Point &pRef=c;//pRef是Point类的引用变量,被c初始化
cout<<″pRef:″<
return 0;
}
程序编译通过,运行结果为
original circle:(输出原来的圆的数据)
x=3.5, y=6.4, r=5.2, area=84.9486
new circle:(输出修改后的圆的数据)
Center=[5,5], r=7.5, area=176.714
pRef:[5,5] (输出圆的圆心“点”的数据)
(3)声明Circle的派生类Cylinder前面已从基类Point派生出Circle类,现在再从Circle派生出Cylinder类。
class Cylinder:public Circle// Cylinder是Circle的公用派生类
{
public :
Cylinder (float x=0,float y=0,float r=0,float h=0);//构造函数
void setHeight(float );//设置圆柱高
float getHeight( )const;//读取圆柱高
loat area( )const;//计算圆表面积
float volume( )const;//计算圆柱体积
friend ostream& operator <<(ostream&,const Cylinder&);//重载运算符<<”
protected :
float height;//圆柱高
};
//定义构造函数
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::getHeight( )const {return height;}
//计算圆表面积
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<<″Center=[″<
return output;
} //重载运算符“<<”
可以写出下面的主函数:
int main( )
{
Cylinder cy1(3.5,6.4,5.2,10);//定义Cylinder类对象cy1
cout<<″\\noriginal cylinder:\\nx=″<
<
<<″,volume=″<
cy1.setHeight(15);//设置圆柱高
cy1.setRadius(7.5);//设置圆半径
cy1.setPoint(5,5);//设置圆心坐标值x,y
cout<<″\\nnew cylinder:\\n″<
Point &pRef=cy1;//pRef是Point类对象的引用变量
cout<<″\\npRef as a Point:″<
Circle &cRef=cy1;//cRef是Circle类对象的引用变量
cout<<″\\ncRef as a Circle:″<
return 0;
}
运行结果如下:
original cylinder:(输出cy1的初始值)
x=3.5, y=6.4, r=5.2, h=10 (圆心坐标x,y。半径r,高h)
area=496.623, volume=849.486 (圆柱表面积area和体积volume)
new cylinder: (输出cy1的新值)
Center=[5,5], r=7.5, h=15 (以[5,5]形式输出圆心坐标)
area=1060.29, volume=2650.72(圆柱表面积area和体积volume)
pRef as a Point:[5,5] (pRef作为一个“点”输出)
cRef as a Circle:Center=[5,5], r=7.5, area=176.714(cRef作为一个“圆”输出)
在本例中存在静态多态性,这是运算符重载引起的。可以看到,在编译时编译系统即可以判定应调用哪个重载运算符函数。
在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型都相同而功能不同的函数。编译系统按照同名覆盖的原则决定调用的对象。
在例12.1程序中用cy1.area( )调用的是派生类Cylinder中的成员函数area。如果想调用cy1中的直接基类Circle的area函数,应当表示为:cy1.Circle::area( )。用这种方法来区分两个同名的函数。
但是这样做很不方便。人们提出这样的设想,能否用同一个调用形式,既能调用派生类又能调用基类的同名函数。在程序中不是通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们。
例如,用同一个语句“pt->display( );”可以调用不同派生层次中的display函数,只需在调用前给指针变量pt赋以不同的值(使之指向不同的类对象)即可。C++中的虚函数就是用来解决这个问题的。
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
请分析例12.2。这个例子开始时没有使用虚函数,然后再讨论使用虚函数的情况。
例12.2 基类与派生类中有同名函数。在下面的程序中Student是基类,Graduate是派生类,它们都有display这个同名的函数。
#include
#include
using namespace std;
//声明基类Student
class Student
{
public:Student(int, string,float);//声明构造函数void display( );//声明输出函数
protected ://受保护成员,派生类可以访问
int num;
string name;
float score;
};
//Student类成员函数的实现
Student::Student(int n, string nam,float s)//定义构造函数{num=n;name=nam;score=s;}
void Student::display( )//定义输出函数{cout<<″num:″<