继承和派生
继承
继承是面向对象的程序设计的重要特色之一。面向对象的程序设计通过数据抽象,对具有共同属性和行为的事物用类进行描述。我们可以对事物按层次进行分类,把处于上层的抽象事物具有下层抽象事物的共同属性(数据成员)和行为(成员函数);面处于下层抽象事物除具有上层的抽象事物所有的属性和行为外,不具有本身所特有的特征,例如:动物可分为有脊椎动物和无脊椎动物,有脊椎动物事分为鱼类、两栖类、爬行类、鸟类和哺乳类;哺乳类动物分为猫科等,猫科动物又分为猫,老虎,狮子,豹等。
在面向对象的程序设计中,继承类似于动物的分层关系。一个类可以从另一个类中继承特征,称为派生一个类;所派生的类称为派生类(子类);上层的被派生的类被称为基类(父类)。
派生类的定义
定义派生类的格式如下:
class 派生类名:访问控制 基类名
{
成员表
};
其中访问控制包括:public(公有派生)、protected(保护派生)和 private (私有派生)。
基类中的访问权限在派生类中的继承关系如下表:
访问权限的继承
派生性质 | 在基类中的访问权限 | 在派生类中的访问权限 |
public (公有派生) |
public | public |
protected | protected | |
private | 不可访问 | |
protected (保护派生) |
public | protected |
protected | protected | |
private | 不可访问 | |
private (私有派生) |
public | private |
protected | private | |
private | 不可访问 |
例:定义一个点和一个矩形类:
class Point {
protect:
int x,y;
public:
Point():x(0),y(0){ }
Point(int xx=0,int yy=0):x(xx),y(yy) { }
int getx(){ return x;}
int gety(){ return y;}
};
class Rectangle : public Point {
private:
int width,high;
public:
Rectangle(){width=0; high=0;}
Rectangle(int w,int h){width=w; high=h;}
int getwidth() { return width;}
int gethigh(){ return high;}
long area(){ return width*high; }
};
下面来看一个具体的例子:
计算球、圆柱、圆锥的表面积和体积。
分析:由于都要用到圆的半径,后两者还要用到圆的面积,所以把圆定义成基类。
#include <iostream.h>
#include <math.h>
#define PI 3.14159
class Circle { //圆类
protected:
double r; //半径
public:
Circle(double radius=0):r(radius){ }
double area() { return PI*r*r;} //圆的表面积
double volume() {return 0 } //计算圆的体积
};
class Sphere: public Circle { //球体类
public:
Sphere(double radius=0):Circle(radius){ }
double area() { return 4*PI*r*r; } //计算球的表面积
double volume() { return 4*PI*pow(r,3)/3; } //计算球的体积
};
class Cylinder: public Circle { //圆柱类
private:
double h; //高度
public:
Cylinder(double radius=0,double height=0):Circle(radius){
h=height;
}
double area() { return 2*PI*r*(r+h); } //计算圆柱的表面积
double volume() { return PI*r*r*h; } //计算圆柱的体积
};
class Cone: public Circle { //圆锥类
private:
double h; //高度
public:
Cone(double radius=0,double height=0):Circle(radius){
h=height;
}
double area() { //计算圆锥的表面积
double he=sqrt(h*h+r*r);
return *PI*r*(r+he); }
double volume() { return PI*r*r*h/3; } //计算圆锥的体积
};
void main()
{
Circle r1(2);
Sphere r2(2);
Cylinder r3(2,3);
Cone r4(2,3);
cout <<"Circle:"<<r1.area()<<" "<<r1.volume()<<endl;
cout <<"sphere:"<<r2.area()<<" "<<r2.volume()<<endl;
cout <<"Cylinder:"<<r3.area()<<" "<<r3.volume()<<endl;
cout <<"Cone:"<<r1.area()<<" "<<r1.volume()<<endl;
运行结果:
Circle:12.5664 0
sphere:50.2655 33.5103
Cylinder:62.8319 37.6991
Cone:35.2207 12.5664
构造函数、析构函数和继承的关系
利用派生类定义对象时,先调用基类的构造函数,然后才派生类的构造函数;析构函数以相反的顺序被调用。如:
#include <iostream.h>
class AX {
int x;
public:
AX(int xx=0):x(xx){
cout <<"AX constructor."<<endl;
}
~AX() { cout<<"AX destructor."<<endl;}
void output(){ cout <<x<<" ";}
};
class BX : public AX {
int y;
AX z;
public:
BX(int xx=0,int yy=0):AX(xx),y(yy),z(xx+yy)
{
cout<<"BX constructor."<<endl;
}
~BX() { cout <<"BX destructor."<<endl;}
}
void output()
{
AX::output;
cout<<" "<<y<<" " <<z.get()<<endl;
}
};
void main()
{
BX a(5),b(10,20);
a.output();
b.output();
}
程序的运行结果为:
AX constructor.
AX constructor.
BX constructor.
AX constructor.
AX constructor.
BX constructor.
5 0 5
10 20 30
BX destructor.
AX destructor.
AX destructor.
BX destructor.
AX destructor.
AX destructor.