第(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类对象cylinderpoint.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、使用虚函数提高了程序的可扩充性。
#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;
}
#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;
}