发表时间:2022-03-25来源:网络
继承性也是程序设计中的一个非常有用的、有力的特性, 它可以让程序员在既有类的基础上,通过增加少量代码或修改少量代码的方法得到新的类, 从而较好地解决了代码重用的问题。
在类名 employee 的冒号之后, 跟着关键字 public 与类名 person,这就意味着类 employee 将继承类 person 的全部特性。
关键字 public 指出派生的方式,告诉编译程序派生类employee从基类 person 公有派生。
声明一个派生类的一般格式为:
class 派生类名∶派生方式 基类名 { // 派生类新增的数据成员和成员函数 } ;派生方式”可以是关键字 private 或 public。如果使用了 private, 则称派生类从基类私有派生; 如果使用了 public,则称派生类从基类公有派生。派生方式可以缺省, 这时派生方式默认为private ,即私有派生。
1. 公有派生
class employee∶public person { // … };2. 私有派生
class employee∶private person { // … } ;这两种派生方式的特点如下:
无论哪种派生方式, 基类中的私有成员既不允许外部函数访问, 也不允许派生类中的成员函数访问,但是可以通过基类提供的公有成员函数访问。公有派生与私有派生的不同点在于基类中的公有成员在派生类中的访问属性。公有派生时, 基类中的所有公有成员在派生类中也都是公有的。
私有派生时, 基类中的所有公有成员只能成为派生类中的私有成员。
下面我们分别讨论私有派生和公有派生的一些特性。
私有派生(1 ) 私有派生类对基类成员的访问
由私有派生得到的派生类, 对它的基类的公有成员只能是私有继承。也就是说基类的所有公有成员都只能成为私有派生类的私有成员, 这些私有成员能够被派生类的成员函数访问,但是基类私有成员不能被派生类成员函数访问。
对于派生类的对象的引用,也有相同的结论, 例如:
Y obj;
obj .f( ) ; / / 被调用的函数是 Y∷f( )
如果要使用基类中声明的名字,则应使用作用域运算符限定, 例如:
obj .X∷f( ) ; / / 被调用的函数是 X∷f( )
protected 说明符可以放在类声明的任何地方,通常将它放在私有成员声明之后, 公有成员声明之前。类声明的一般格式如下所示:
class 类名 { [private:] 私有数据成员和成员函数 protected: 保护数据成员和成员函数 public: 公有数据成员和成员函数 };保护成员可以被派生类的成员函数访问,但是对于外界是隐藏起来的, 外部函数不能访问它。因此,为了便于派生类的访问, 可以将基类私有成员中需要提供给派生类访问的成员定义为保护成员。
下面的程序说明类的私有成员、公有成员与保护成员是如何被访问的。
程序运行结果如下:
Constructing base class
Constructing derived class
Destructing derived class
Destructing base class
构造函数的调用严格地按照先调用基类的构造函数, 后调用派生类的构造函数的顺序执行。析构函数的调用顺序与构造函数的调用顺序正好相反,先调用派生类的析构函数, 后调用基类的析构函数。
当基类的构造函数没有参数,或没有显式定义构造函数时, 派生类可以不向基类传递参数,甚至可以不定义构造函数。
派生类不能继承基类中的构造函数和析构函数。当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径。
在 C + + 中,派生类构造函数的一般格式为:
其中基类构造函数的参数,通常来源于派生类构造函数的参数表, 也可以用常数值。
下面的程序说明如何传递一个参数给派生类的构造函数和传递一个参数给基类的构造函数。
在定义派生类对象时,构造函数的执行顺序如下:
基类的构造函数对象成员的构造函数派生类的构造函数撤消对象时,析构函数的调用顺序与构造函数的调用顺序正好相反。
下面这个程序说明派生类构造函数和析构函数的执行顺序。
程序执行结果如下:
Constructing base class
Constructing base class
Constructing derived class
x = 5
Destructing derived class
Destructing base class
Destructing base class
说明:
前面我们介绍的派生类只有一个基类, 这种派生方法称为单基派生或单一继承。当一个派生类具有多个基类时,这种派生方法称为多基派生或多重继承。
一般形式如下:
class 派生类名: 派生方式 1 基类名 1, …,派生方式 n 基类名 n { // 派生类新增的数据成员和成员函数 } ;冒号后面的部分称基类表,各基类之间用逗号分隔, 其中“派生方式 i”( i = 1, 2, …, n )规定了派生类从基类中按什么方式继承: private 或 public,缺省的派生方式是 private
class z: public x, y { // 类 z 公有继承了类 x,私有继承了类 y // … }; class z: x, public y { // 类 z 私有继承了类 x,公有继承了类 y // … }; class z: public x, public y { // 类 z 公有继承了类 x 和类 y // … };在多重继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则相同。
#include using namespace std; class X { int a ; public: void setX(int x) { a = x; } void showX() { cout b = x; } void showY() { cout c = x; setY(y) ; } void showZ() { showY(); cout public: int f(); }; class Y { public: int f(); int g(); }; class Z∶public X, public Y { public: int g(); int h(); };假如定义类 Z 的对象 obj: Z obj;
则以下对函数 f( )的访问是二义的:
obj .f( ) ;
使用成员名限定可以消除二义性,例如:
obj .X∷f( ) ;
obj .Y∷f( ) ;
/ / 调用类 Y 的 f( )多重继承构造函数的定义形式与单继承构造函数的定义形式相似, 只是 n 个基类的构造函数之间用“,”分隔。多重继承构造函数定义的一般形式如下:
派生类构造函数名(参数表) :基类 1 构造函数名 ( 参数表), 基类 2 构造函数名 (参数表), …,基类 n 构造函数名(参数表) { // … }例如,由一个硬件类 Hard 和一个软件类 Soft ,它们共同派生出系统类 System, 声明如下:
class Hard { protected: char bodyname[20]; public: Hard(char * bdnm ); // 基类 Hard 的构造函数 // … }; class Soft { protected: char os[10]; char Lang[15]; public: Soft( char * o, char * lg);// 基类 Soft 的构造函数 // … } ; class System: public Hard, public Soft { private: char owner[10] ; public: System( char * ow, char * bn, char * o, char * lg) // 派生类 System 的构造函数 ∶Hard( bn), Soft(o, lg); // 缀上了基类 Hard 和 Soft 的构造函数 // … };注意:在定义派生类 System 的构造函数时,缀上了 Hard 和 Soft 的构造函数。
再如,现有一个窗口类 window 和一个滚动条类 scrollbar, 它们可以共同派生出一个带有滚动条的窗口,声明如下:
在这个例子中, 定义派生类 scrollbarwind 的构造函数时, 也缀上了基类 window 和scrollbar 的构造函数。
下面我们再看一个程序,其中类 X 和类 Y 是基类, 类 Z 是类 X 和类 Y 共同派生出来的,请注意类 Z 的构造函数的定义方法。
定义类 X 的对象 one 时,将产生如下的调用次序:
Z( ) ;
Y( ) ;
X( ) ;
此例中,派生类 AA 由类 X、类 Y 和类 Z 派生而来。AA 与它的间接基类 B 之间的对应关系是:类 B 既是 X、Y 继承路径上的一个虚基类, 也是 Z 继承路径上的一个非虚基类。
下一篇:c++中list的基本语法