您好,欢迎来电子发烧友网! ,新用户?[免费注册]

当前位置:电子发烧友网 > 图书频道 > 电子 > 《C++程序设计实践例题》 > 第4章 第四章

第3节 第三部分

例12.1 先建立一个Point(点)类,包含数据成员x,y(坐标点)。以它为基类,派生出一个Circle(圆)类,增加数据成员r(半径),再以Circle类为直接基类,派生出一个Cylinder(圆柱体)类,再增加数据成员h(高)。要求编写程序,重载运算符“<<”和“>>”,使之能用于输出以上类对象。

对于一个比较大的程序,应当分成若干步骤进行。先声明基类,再声明派生类,逐级进行,分步调试。

(1) 声明基类Point类

可写出声明基类Point的部分如下:

#include <iostream>

 

//声明类Point

classPoint

{public:

  Point(floatx=0,floaty=0);//有默认参数的构造函数

  voidsetPoint(float,float);                 //设置坐标值

  floatgetX( ) const{returnx;}              //读x坐标

  floatgetY( ) const{returny;}              //读y坐标

  friendostream & operator<<(ostream &,constPoint &);//重载运算符“<<”

protected:                                   //受保护成员

  floatx,y;

};

//下面定义Point类的成员函数

 

//Point的构造函数

Point::Point(floata,floatb)                 //对x,y初始化

{x=a;y=b;}

//设置x和y的坐标值

voidPoint::setPoint(floata,floatb)         //为x,y赋新值

{x=a;y=b;}

//重载运算符“<<”,使之能输出点的坐标

ostream & operator<<(ostream &output,constPoint &p)

{output<<"["<<p.x<<","<<p.y<<"]"<<endl;

 returnoutput;

}

以上完成了基类Point类的声明。

现在要对上面写的基类声明进行调试,检查它是否有错,为此要写出main函数。实际上它是一个测试程序。

intmain( )

{Point p(3.5,6.4);//建立Point类对象p

 cout<<"x="<<p.getX( )<<",y="<<p.getY( )<<endl;//输出p的坐标值

 p.setPoint(8.5,6.8);                            //重新设置p的坐标值

 cout<<"p(new):"<<p<<endl;                       //用重载运算符“<<”输出p点坐标

}

程序编译通过,运行结果为

x=3.5,y=6.4

p(new):[8.5,6.8]

测试程序检查了基类中各函数的功能,以及运算符重载的作用,证明程序是正确的。

(2) 声明派生类Circle

在上面的基础上,再写出声明派生类Circle的部分:

classCircle:publicPoint//circle是Point类的公用派生类

{public:

  Circle(floatx=0,floaty=0,floatr=0); //构造函数

  voidsetRadius(float);                 //设置半径值

  floatgetRadius( ) const;               //读取半径值

  floatarea ( ) const;                   //计算圆面积

  friendostream &operator<<(ostream &,constCircle &);//重载运算符“<<”

 private:

  floatradius;

};

 

//定义构造函数,对圆心坐标和半径初始化

Circle::Circle(floata,floatb,floatr):Point(a,b),radius(r){ }

//设置半径值

voidCircle::setRadius(floatr)

{radius=r;}

//读取半径值

floatCircle::getRadius( ) const{returnradius;}

//计算圆面积

floatCircle::area( ) const

{return3.14159*radius*radius;}

//重载运算符“<<”,使之按规定的形式输出圆的信息

ostream &operator<<(ostream &output,constCircle &c)

{output<<"Center=["<<c.x<<","<<c.y<<"],r="<<c.radius<<",area="<<c.area( )<<endl;

 returnoutput;

}为了测试以上Circle类的定义,可以写出下面的主函数:intmain( )

{Circle c(3.5,6.4,5.2);//建立Circle类对象c,并给定圆心坐标和半径

 cout<<"original circle:\\nx="<<c.getX()<<", y="<<c.getY()<<", r="<<c.getRadius( )

     <<", area="<<c.area( )<<endl;     //输出圆心坐标、半径和面积

 c.setRadius(7.5);                   //设置半径值

 c.setPoint(5,5);                    //设置圆心坐标值x,y

 cout<<"new circle:\\n"<<c;           //用重载运算符“<<”输出圆对象的信息

 Point &pRef=c;                      //pRef是Point类的引用变量,被c初始化

 cout<<"pRef:"<<pRef;                //输出pRef的信息

 return0;

}程序编译通过,运行结果为original circle:(输出原来的圆的数据)

x=3.5, y=6.4, r=5.2, area=84.9486

newcircle:                                (输出修改后的圆的数据)

Center=[5,5], r=7.5, area=176.714

pRef:[5,5]                                 (输出圆的圆心“点”的数据)

(3) 声明Circle的派生类Cylinder

前面已从基类Point派生出Circle类,现在再从Circle派生出Cylinder类。

classCylinder:publicCircle// Cylinder是Circle的公用派生类

{public:

  Cylinder (floatx=0,floaty=0,floatr=0,floath=0);//构造函数

  voidsetHeight(float);                      //设置圆柱高

  floatgetHeight( ) const;                    //读取圆柱高

  floatarea( ) const;                         //计算圆表面积

  floatvolume( ) const;                       //计算圆柱体积

  friendostream& operator<<(ostream&,constCylinder&);//重载运算符“<<”

 protected:

  floatheight;                               //圆柱高

};

//定义构造函数

Cylinder::Cylinder(floata,floatb,floatr,floath) 

    :Circle(a,b,r),height(h){}

//设置圆柱高

voidCylinder::setHeight(floath){height=h;}

//读取圆柱高

floatCylinder::getHeight( ) const{returnheight;}

//计算圆表面积

floatCylinder::area( ) const

{ return2*Circle::area( )+2*3.14159*radius*height;}

//计算圆柱体积

floatCylinder::volume() const

{returnCircle::area()*height;}

//重载运算符“<<”

ostream &operator<<(ostream &output,constCylinder& cy)

{output<<"Center=["<<cy.x<<","<<cy.y<<"],r="<<cy.radius<<",h="<<cy.height

       <<"\\narea="<<cy.area( )<<", volume="<<cy.volume( )<<endl;

 returnoutput;

}

可以写出下面的主函数:

intmain( )

{Cylinder cy1(3.5,6.4,5.2,10);//定义Cylinder类对象cy1

 cout<<"\\noriginal cylinder:\\nx="<<cy1.getX( )<<", y="<<cy1.getY( )<<", r="

     <<cy1.getRadius( )<<", h="<<cy1.getHeight( )<<"\\narea="<<cy1.area()

     <<",volume="<<cy1.volume()<<endl;//用系统定义的运算符“<<”输出cy1的数据

 cy1.setHeight(15);                     //设置圆柱高

 cy1.setRadius(7.5);                    //设置圆半径

 cy1.setPoint(5,5);                     //设置圆心坐标值x,y

 cout<<"\\nnew cylinder:\\n"<<cy1;        //用重载运算符“<<”输出cy1的数据

 Point &pRef=cy1;                       //pRef是Point类对象的引用变量

 cout<<"\\npRef as a Point:"<<pRef;      //pRef作为一个“点”输出

 Circle &cRef=cy1;                      //cRef是Circle类对象的引用变量

 cout<<"\\ncRef as a Circle:"<<cRef;     //cRef作为一个“圆”输出

 return0;

}

运行结果如下:

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)

 

newcylinder:                              (输出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.2 基类与派生类中有同名函数。

在下面的程序中Student是基类,Graduate是派生类,它们都有display这个同名的函数。

#include <iostream>

#include <string>

usingnamespacestd;

//声明基类Student

classStudent

{public:

   Student(int, string,float);//声明构造函数

   voiddisplay( );                                             //声明输出函数

  protected:                                      //受保护成员,派生类可以访问

   intnum;

   string name;

   floatscore;

 };

//Student类成员函数的实现

Student::Student(intn, string nam,floats)                     //定义构造函数

 {num=n;name=nam;score=s;}

 

voidStudent::display( )                                        //定义输出函数

{cout<<"num:"<<num<<"\\nname:"<<name<<"\\nscore:"<<score<<"\\n\\n";}

 

//声明公用派生类Graduate

classGraduate:publicStudent

{public:

   Graduate(int, string, float, float);                          //声明构造函数

   voiddisplay( );                                             //声明输出函数

private:

  floatpay;

};

// Graduate类成员函数的实现

voidGraduate::display( )                                       //定义输出函数

 {cout<<"num:"<<num<<"\\nname:"<<name<<"\\nscore:"<<score<<"\\npay="<<pay<<endl;}

 

Graduate::Graduate(intn, string nam,floats,floatp):Student(n,nam,s),pay(p){ }

 

//主函数

intmain()

 {Student stud1(1001,"Li",87.5);                   //定义Student类对象stud1

  Graduate grad1(2001,"Wang",98.5,563.5);          //定义Graduate类对象grad1

  Student *pt=&stud1;                              //定义指向基类对象的指针变量pt

  pt->display( );

  pt=&grad1;

  pt->display( );

  return0;

 }

 

例12.3 基类中有非虚析构函数时的执行情况。

为简化程序,只列出最必要的部分。

#include <iostream>

usingnamespacestd;

classPoint//定义基类Point类

{public:

  Point( ){ }                                                   //Point类构造函数

  ~Point(){cout<<"executing Point destructor"<<endl;}//Point类析构函数

};

 

classCircle:publicPoint                                     //定义派生类Circle类

{public:

  Circle( ){ }                                                 //Circle类构造函数

  ~Circle( ){cout<<"executing Circle destructor"<<endl;}//Circle类析构函数

 private:

  intradius;

};

 

intmain( )

{ Point *p=newCircle;                             //用new开辟动态存储空间

deletep;                                        //用delete释放动态存储空间

return0;

}

 

例12.4 虚函数和抽象基类的应用。

在本章例12.1介绍了以Point为基类的点—圆—圆柱体类的层次结构。现在要对它进行改写,在程序中使用虚函数和抽象基类。类的层次结构的顶层是抽象基类Shape(形状)。Point(点), Circle(圆), Cylinder(圆柱体)都是Shape类的直接派生类和间接派生类。

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

程序如下:

第(1)部分

#include <iostream>

usingnamespacestd;

//声明抽象基类Shape

classShape

{public:

 virtualfloatarea( ) const{return0.0;}//虚函数

 virtualfloatvolume() const{return0.0;}      //虚函数

 virtualvoidshapeName() const=0;              //纯虚函数

};

第(2)部分

//声明Point类

classPoint:publicShape//Point是Shape的公用派生类

{public:

  Point(float=0,float=0);

  voidsetPoint(float,float);

  floatgetX( ) const{returnx;}

  floatgetY( ) const{returny;}

  virtualvoidshapeName( ) const{cout<<"Point:";}      //对虚函数进行再定义

  friendostream & operator<<(ostream &,constPoint &);

protected:

  floatx,y;

};

//定义Point类成员函数

Point::Point(floata,floatb)

{x=a;y=b;}

 

voidPoint::setPoint(floata,floatb)

{x=a;y=b;}

 

ostream & operator<<(ostream &output,constPoint &p)

{output<<"["<<p.x<<","<<p.y<<"]";

returnoutput;

}

第(3)部分

//声明Circle类

classCircle:publicPoint

{public:

  Circle(floatx=0,floaty=0,floatr=0);

  voidsetRadius(float);

  floatgetRadius( ) const;

  virtualfloatarea( ) const;

  virtualvoidshapeName( ) const{cout<<"Circle:";}//对虚函数进行再定义

  friendostream &operator<<(ostream &,constCircle &);

protected:

  floatradius;

};

//声明Circle类成员函数

Circle::Circle(floata,floatb,floatr):Point(a,b),radius(r){ }

 

voidCircle::setRadius(floatr):radius(r){ }

 

floatCircle::getRadius( ) const{returnradius;}

 

floatCircle::area( ) const{return3.14159*radius*radius;}

 

ostream &operator<<(ostream &output,constCircle &c)

{output<<"["<<c.x<<","<<c.y<<"], r="<<c.radius;

 returnoutput;

}

第(4)部分

//声明Cylinder类

classCylinder:publicCircle

{public:

  Cylinder (floatx=0,floaty=0,floatr=0,floath=0);

  voidsetHeight(float);

  virtualfloatarea( ) const;

  virtualfloatvolume( ) const;

  virtualvoidshapeName( ) const{cout<<"Cylinder:";}//对虚函数进行再定义

  friendostream& operator<<(ostream&,constCylinder&);

 protected:

  floatheight;

};

//定义Cylinder类成员函数

Cylinder::Cylinder(floata,floatb,floatr,floath)

    :Circle(a,b,r),height(h){ }

 

voidCylinder::setHeight(floath){height=h;}

 

floatCylinder::area( ) const

{ return2*Circle::area( )+2*3.14159*radius*height;}

 

floatCylinder::volume( ) const

{returnCircle::area( )*height;}

 

ostream &operator<<(ostream &output,constCylinder& cy)

{output<<"["<<cy.x<<","<<cy.y<<"], r="<<cy.radius<<", h="<<cy.height;

returnoutput;

}

第(5)部分

//main函数

intmain( )

{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";

 return0;

}