虚函数和抽象基类的应用 Point(点),Circle(圆),Cylinder (圆柱体) - 飘凌大杂烩
飘凌大杂烩电脑网络手机数码计算机科学与技术虚函数和抽象基类的应用 Point(点),Circle(圆),Cylinder (圆柱体)
    
 
虚函数和抽象基类的应用 Point(点),Circle(圆),Cylinder (圆柱体)
发起人:piaoling  回复数:2  浏览数:8927  最后更新:2009/12/11 17:09:31 by piaoling

选择查看 搜索更多相关主题  帖子排序:
2009/11/22 16:18:01
piaoling






角  色:管理员
等  级:旅长
发 帖 数:672
经 验 值:2001
注册时间:2008/12/7
虚函数和抽象基类的应用 Point(点),Circle(圆),Cylinder (圆柱体)
在本章例1介绍了以Point为基类的点一圆一圆柱体类的层次结构。现在要对它 进行改写,在程序中使用虚函数和抽象基类。类的层次结构的顶层是抽象基类Shape(形 状)。Point(点),Circle(圆),Cylinder (圆柱体)都是Shape类的直接派生类和间接派生类,下面是一个完整的程序,程序如下:

第(1)部分
#include <iostream> //声明抽象基类Shape
using namespace std;
class Shape
   { public:
      virtual float area() const {return 0.0;}   //虚函数
      
virtual float volume() const {return 0.0;} //虚函数
      
virtual void shapeName() const =0;};      //纯虚函数

   
Shape类有3个成员函数,没有数据成员。3个成员函数都声明为虚函数,其中shapeName声明为纯虚函数,因此Shape是一个抽象基类。shapeName函数的作用是输出具体的形状(如点、圆、圆柱体)的名字,这个信息是与相应的派生类密切相关的,显然这不应当在基类中定义,而应在派生类中定义。所以把它声明为纯虚函数。Shape虽然是抽象基类,但是也可以包括某些成员的定义部分。类中两个函数area(面积)和volume(体积)包括函数体,使其返回值为0(因为可以认为点的面积和体积都为0)。由于考虑到在Point类中不再对area和volume函数重新定义,因此没有把area和volume函数也声明为纯虚函数。 在Point类中继承了Shape类的area和volume函数。这3个函数在各派生类中都要用到。

第(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(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)//重载<<运算符
   
{  utput<<"["<<p.x<<","<<p.y<<"]";
return output; }

   Point从Shape继承了3个成员函数,由于“点”是没有面积和体积的,因此不必重新定义area和volume。虽然在Point类中用不到这两个函数,但是Point类仍然从Shape类继承了这两个函数,以便其派生类继承它们。shapeName函数在Shape类中是纯虚函数,在Point类中要进行定义。Point类还有自己的成员函数(setPoint,getX,getY)和数据成员(x和y)。

第(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(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; }

   在Circle类中要重新定义ama函数,因为需要指定求圆面积的公式。由于圆没有体积,因此不必重新定义volume函数,而是从Point类继承volume函数。shapeName函数是虚函数,需要重新定义,赋予新的内容(如果不重新定义,就会继承Point类中的shapeName函数)。此外,Circle类还有自己新增加的成员函数(setRadius,getRadius)和数据成员(radius)。

第(4)部分
//声明Cylinder类
class Cylinder:public Circle
   { public:
      Cylinder (float x=0,float y=0,float r=0,float h=0);
      void setHeight(float);
      float getHeight() const;
      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(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<<"["<<cy.x<<","<<cy.y<<"], r="<<cy.radius<<", h="<<cy.height;
      return output; }

   Cylinder类是从Circle类派生的。由于圆柱体有表面积和体积,所以要对afea和volume函数重新定义。虚函数shapeName也需要重新定义。此外,Cylinder类还有自己的成员函数setHeight和数据成员radius。

第(5)部分

int main()
 { Point point(3.2,4.5); //建立Point类对象point
   
Circle circle(2.4,12,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类对象pomt的数据:点的坐标)
Circle:[2.4,l.2],r=5.6 (Circle类对象circle的数据:圆心和半径)
Cylinder:[3.5,6.4],r=5.5,h=lO.5 (Cylinder类对象cylinder的数据:圆心、半径和高)
Point:x=3.2,y=4.5 (输出Point类对象pomt的数据:点的坐标)
area=O           (点的面积)
volume=O         (点的体积)
Circle:x=2.4,y=1.2 (输出Circle类对象circle的数据:圆心坐标)
area=98.5203       (圆的面积)
volume=O          (圆的体积)
Cylinder:x=3.5,y=6.4 (输出Cylinder类对象cylinder的数据:圆心坐标)
area=512.595       (圆的面积)
volume=891.96      (圆柱的体积)

从本例可以进一步明确以下结论:

   1、一个基类如果包含一个或一个以上纯虚函数,就是抽象基类
   2、抽象基类与普通基类不同它可以没有任何物理上的或其他实体
   3、在类的层次结构中,顶层或最上面的几层可以是际意义方面的含义。
   
4、抽象基类是本类族的公共接口。或者说,从同一基类派生出的多个类有同一接口。因此能响应同一形式的消息
   5、区别静态关联和动态关联。
   6、如果在基类声明了虚函数,则在派生类中凡是与该函数有相同的函数名、函数类 型、参数个数和参数类型的函数,均为虚函数(不论在派生类中是否用virtual声明)。
   7、使用虚函数提高了程序的可扩充性。

2009/12/11 15:07:40
piaoling






角  色:管理员
等  级:旅长
发 帖 数:672
经 验 值:2001
注册时间:2008/12/7

#include<iostream>
#include<math.h>
using namespace std;
class Shape                      //抽象基类 Shpae
{
public:
   virtual double area()=0;
   virtual void shapeName(){}    
};
class Circle:public Shape       //圆形 Circle
{
public:
        //Circle();
        Circle(double r){radius=r;}
        void shapeName(){cout<<"Circle: ";}
        double area(){return 3.14*radius*radius;}
private:
        double radius;          
};

class Rectangle:public Shape      //矩形 Rectangle
{
public:
        //Rectangle();
        Rectangle(double a,double b){sidea=a;sideb=b; }           
        void shapeName(){cout<<"Rectangle: ";}
        double area(){return sidea*sideb;}
private:
         double sidea;
         double sideb;            
};

class Triangle:public Shape       //Triangle(三角形)
{
public:
        //Triangle();
        Triangle(double a,double b,double c){sidea=a;sideb=b;sidec=c;}
        void shapeName(){cout<<"Triangle: ";}
        double area()
        {
                double s=(sidea+sideb+sidec)/2;
                double m=s*(s-sidea)*(s-sideb)*(s-sidec);
                return sqrt(m);
         }
private:
         double sidea;
         double sideb;
         double sidec;
};
int main()
{
    Circle C1(5.58);
    Rectangle R1(6.34,8.64);
    Triangle T2(6.54,5.13,3.89);
    Shape *pt[3];
   
    pt[0]=&C1;
    pt[0]->shapeName();
    cout << pt[0]->area()<<endl;
 
    pt[1]=&R1;
    pt[1]->shapeName();
    cout << pt[1]->area()<<endl;
   
    pt[2]=&T2;
    pt[2]->shapeName();
    cout << pt[2]->area()<<endl;
   
    float areaSum=0;
    for(int i=0;i<3;i++)
     {areaSum=areaSum+pt->area();}
    cout<<"areaSum: "<<areaSum<<endl;
    system("pause");
    return 0;   
}

2009/12/11 17:09:31
piaoling






角  色:管理员
等  级:旅长
发 帖 数:672
经 验 值:2001
注册时间:2008/12/7

#include<iostream>

#include<math.h>

using namespace std;

class Base                      //抽象基类 Shape

{

public:

virtual double area()=0;        //计算输出图形面积

   virtual void shape()=0;     //描述图形的名称

};

class Circle:public Base       //圆形 Circle

{

public:

        Circle(double r){radius=r;}

        void shape(){cout<<"Circle: ";}

        double area(){return 3.14*radius*radius;}

private:

        double radius;          

};

 

class Square:public Base      //正方形 square

{

public:

        Square(double a){sidea=a;}           

        void shape(){cout<<"Square: ";}

        double area(){return sidea*sidea;}

private:

         double sidea;

};

 

class Rectangle:public Base      //矩形 Rectangle

{

public:

        Rectangle(double a,double b){sidea=a;sideb=b; }           

        void shape(){cout<<"Rectangle: ";}

        double area(){return sidea*sideb;}

private:

         double sidea;

         double sideb;            

};

 

class Trapezoid:public Base      //梯形 Trapezoid

{

public:

        Trapezoid(double a,double b,double h){sidea=a;sideb=b;sideh=h; }            

        void shape(){cout<<"Trapezoid: ";}

        double area(){return (sidea+sideb)*sideh/2;}

private:

         double sidea;

         double sideb;

               double sideh;

};

 

class Triangle:public Base       //Triangle(三角形)

{

public:

        Triangle(double a,double b,double c){sidea=a;sideb=b;sidec=c;}

        void shape(){cout<<"Triangle: ";}

        double area()

        {

                double s=(sidea+sideb+sidec)/2;

                double m=s*(s-sidea)*(s-sideb)*(s-sidec);

                return sqrt(m);

         }

private:

         double sidea;

         double sideb;

         double sidec;

};

int main()

{

    Circle C1(8.4);

       Square S1(3.18);

    Rectangle R1(6.34,8.64);

       Trapezoid T1(2.5,5,4);

    Triangle T2(4.54,5.13,3.89);

    Base *pt[5];

   

    pt[0]=&C1;

    pt[0]->shape();

    cout << pt[0]->area()<<endl;

 

       pt[1]=&S1;

    pt[1]->shape();

    cout << pt[1]->area()<<endl;

 

    pt[2]=&R1;

    pt[2]->shape();

    cout << pt[2]->area()<<endl;

 

       pt[3]=&T1;

    pt[3]->shape();

    cout << pt[3]->area()<<endl;

   

    pt[4]=&T2;

    pt[4]->shape();

    cout << pt[4]->area()<<endl;

   

    system("pause");

    return 0;   

}

返回页首↑


津ICP备09000164号

联系我们 - piaoling Corporation - 论坛存档 - 返回顶端
Powered by BBSXP 2007 ACCESS © 1998-2025
Server Time 2025/1/13 19:54:37
Processed in 0.02 second(s)
飘凌大杂烩