8.3 类的继承与派生
C++语法:定义派生类
class 派生类名 : 继承方式1 基类1, 继承方式2 基类2, ...... // 派生类声明部分
{
public :
新增公有成员
protected :
新增保护成员
private :
新增私有成员
} ;
各新增函数成员的完整定义 // 派生类实现部分
语法说明:
定义派生类时,在派生类名的后面添加继承列表,在声明部分的大括号里声明新增成员,在实现部分编写各新增函
数成员的完整定义代码;
继承列表指定派生类从哪些基类继承。派生类可以只从一个基类继承(单继承),也可以从多个基类继承(多继
承)。每个基类以“继承方式 基类名”的形式声明,多个基类之间用“,”隔开;
派生类将继承基类中除构造函数、析构函数之外的所有数据成员和函数成员。基类的构造函数和析构函数不能被继
承,派生类需重新编写自己的构造函数、析构函数。
继承后,派生类会对其基类成员按照继承方式进行再次封装。继承方式有3种:public(公有继承)、protected(保
护继承)和private(私有继承);
public(公有继承):派生类对其基类成员不做任何封装,它们在派生类中的访问权限与原来在基类中的权限相同;
private(私有继承):派生类对其基类成员做全封装,它们在派生类中的访问权限统统被改为private(私有权限),
不管它们原来在基类中的权限是什么。使用私有继承,实际上是派生类要将其基类成员全部隐藏起来;
protected(保护继承):派生类对其基类成员做半封装。基类中的public成员被继承到派生类后,其访问权限被降
格成protected(保护权限)。基类中的protected、private成员被继承到派生类后,其访问权限保持不变;
在类声明部分的大括号中声明新增的数据成员、函数成员,并指定各新增成员的访问权限。在类实现部分编写各新
增函数成员的完整定义代码。
同名覆盖:派生类中定义与基类成员重名的
新增成员,新增成员将覆盖基类成员。通过
成员名访问时,所访问到的将是新增成员,
这就是新增成员对基类成员的同名覆盖。同
名覆盖后,被覆盖的基类成员仍然存在,只
是被隐藏了。可以访问被覆盖的基类成员,
其访问形式是:基类名 :: 基类成员名
派生类对象的定义与访问
BorderCircle obj;
– 访问公有的基类成员
obj.Circle::Input( )(注,同名覆盖时访问方法)、obj.CRadius( )、obj.CArea( )、obj.CLen( )
– 访问公有的新增成员
obj.w、obj.InnerArea( )、obj.BorderArea( )、obj.Input( )
派生类对象的构造与析构
– 派生类的构造函数
派生类构造函数名( 形参列表 ) : 基类名1( 形参1 ), 基类名2( 形参2 ), ……
{
…… // 在函数体中初始化新增成员
}
– 派生类对象中各数据成员的初始化顺序是:先调用基类构造函数,
初始化基类成员;再执行派生类构造函数的函数体,初始化新增
成员
– 如果派生类继承了多个基类,那么各基类成员的初始化顺序由其
在派生类继承列表中的声明顺序决定,声明在前的基类成员先初
始化
派生类的析构函数
– 派生类对象中数据成员的析构顺序是:先执行派生类析构函
数的函数体,清理新增成员;再调用基类析构函数,清理基
类成员。简单地说,对象的析构顺序与构造顺序相反,即先
析构新增成员,再析构基类成员
• 组合派生类的构造与析构
– 从基类继承来的成员(基类成员),二是新增的对象成员,
三是新增的非对象成员
– 组合派生类的构造函数需依次初始化基类成员、新增对象成
员、新增非对象成员。其中,初始化基类成员和新增对象成
员需通过初始化列表,初始化新增的非对象成员则是在函数
体中直接赋值
– 组合派生类对象中各成员的析构顺序与其构造顺序相反,即
先析构新增的非对象成员,再析构新增对象成员,最后才析
构基类成员
类A1
类A2
class A1
{
public:
int a1;
A1( int x = 0 ) // 构造函数
{ a1 = x; }
} ;
class A2
{
public:
int a2;
A2( int x = 0 ) // 构造函数
{ a2 = x; }
} ;
类B1
类B2
class B1
{
public:
int b1;
B1( int x = 0 ) // 构造函数
{ b1 = x; }
} ;
class B2
{
public:
int b2;
B2( int x = 0 ) // 构造函数
{ b2 = x; }
} ;
组合派生类C
class C : public A1, public A2 // 继承基类A1、A2
{ public:
B1 bObj1; // 类B1的对象成员
bObj1 B2 bObj2; // 类B2的对象成员bObj2
int c;
// 组合派生类的构造函数:初始化基类成员、新增对象成员、新增非对象成员
C( int p1=0, int p2=0, int p3=0, int p4=0, int p5=0 ) : A1(p1), A2(p2), bObj1(p3), bObj2(p4) { c = p5; } } ;
抽象基类减少重复代码,通过继承基类的方法重用这些代码
重新定义C++语言已有运算符的运算规则,使同一运算符作用于不同类型数据时执行不同的运算,这就是运算符重载
–程序员可以为类重载运算符,实现类运算
–重载运算符使用函数的形式来重新定义运算符的运算规则
函数类型 operator 运算符( 形式参数 )
{ 函数体 }
–将运算符函数定义为类的函数成员
–定义为类外的一个友元函数
关系运算符“==”
bool Complex :: operator ==( Complex c )
{
return ( real == c.real && image == c.image ) ;
}
Complex c1(1, 3), c2(2, 4);
if (c1 == c2) // 比较c1、c2是否相等
// ...... 代码省略