类的继承与派生

类及对象的访问权限:

类中的成员函数可以直接访问类中的数据成员(包括私有成员、公有成员、保护成员);

类中的成员函数可以相互访问;

类的对象只能访问类的公有成员,不能访问私有成员及保护成员。


 一、继承与派生

在C++中,类具有继承性所谓继承就是在一个已存在的类的基础上建立一个新的类。

        利用类的继承,可以将原来的程序代码重复使用,从而减少了程序代码的冗余度,符合软件重用的目标。增强编程语言的功能。提高软件开发效率。

在继承关系中,被继承的类称为基类(或父类把通过继承关系创建出来的新类称为派生类(子类)。

派生类不仅可以继承原来类的成员,还可以通过以下方式产生新的成员:
1.增加新的数据成员;
2.增加新的成员函数;
3.重新定义已有成员函数;
4.改变现有成员的属性。


继承的特点:

1>继承具有层次结构。
2>越在上面的类越具有普通性和共性,下层比上层更具体,越在下层越细化、专门化。
3>继承具有传递性,即派生类能自动继承上层基类的全部数据结构及操作方法(数据成员及成员函数)

基类与派生类的对应关系:

单继承:

一个派生类只从一个基类派生,这是最常见的继承形式

多重继承;

一个派生类有两个及两个以上的基类。如:类C从类A和类B派生。

多重派生:

由一个基类派生出多个不同的派生类。

多层派生:

每一个派生类又可以作为基类,再派生出新的派生类。

 基类和派生类之间的关系:

1.基类是对派生类的抽象,派生类是对基类的具体化。基类抽取了它与派生类的公共特征,而派生类通过增加信息将抽象的基类变为某种具体的类型。
2.派生类是基类的组合,可以把多重继承看作是多个单一继承的简单组合。

二、派生类的声明方式

定义派生类的一般形式:

class 派生类名:继承方式 基类名

        派生类新增加的成员

};

继承方式有public(公有继承)、protected(保护继承)和private(私有继承)

1. private方式继承(私有继承):

        基类中的公有成员和保护成员在派生类中皆变为私有成员。

2.public方式继承(公有继承):

基类的公有成员和保护成员被继承为派生类成员时,其访问属性不变。

3.protected方式继承(保护继承):

基类的公有成员和保护成员在派生类中成了保护成员,私有成员仍为基类私有。

无论哪种继承方式,基类的私有成员均不能继承。这与私有成员的定义是一致的,符合数据封装的思想。

三、派生类的构成

1>在一个派生类中,其成员由两部分构成:

        1.从基类继承得到的成员

        2.自己增加的新成员

2>友元关系不能继承。
一方面,基类的友元对派生类的成员没有特殊访问权限。
另一方面,如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的类。

3>如果基类定义了静态成员
无论从基类派生出多少个派生类,基类定义的静态成员,不受继承方式的影响,在整个类层次体系中都可以访问。

4>派生类中访问静态成员,必须用显式说明

                类名::成员

一个派生类应包括4个方面:

1)从基类接收成员

除了构造函数和析构函数,派生类会把基类全部的成员继承过来。这种继承是没有选择的,不能选择接收其中一部分成员,而舍弃另一部分成员。

2)调整基类成员的访问

派生类接收基类成员是程序员不能选择的,但是程序员可以对这些成员作出访问策略。

3)修改基类成员

可以在派生类中声明一个与基类成员同名的成员,则派生类中的新成员会覆盖基类的同名成员,就实现了修改基类成员功能的效果。特别注意,如果是成员函数,不仅函数名相同,而且函数的参数个数和类型都要相同。

4)在定义派生类时增加新的成员

一般还应当自己定义派生类的构造函数和析构函数。

派生类成员的访问属性

私有成员只能被同一类中的成员函数访问。基类的成员函数不能直接访问派生类的成员。

不同的继承方式决定了基类成员在派生类中的访问属性。

公有继承:

基类的公有成员和保护成员在派生类中保持原有访问属性,私有成员仍为基类私有。

私有继承:

基类的所有成员在派生类中为私有成员。

保护继承:

基类的公有成员和保护成员在派生类中成了保护成员,私有成员仍为基类私有。

无论采用何种继承方式得到的派生类,派生类成员及其友元都不能访问基类的私有成员,派生类外部的用户只能访问公有属性的成员。
多级派生的情况下,保护继承和私有继承会进一步地将基类的访问权限隐蔽成不可访问的。
一般地,保护继承与私有继承在实际编程中是极少使用的,它们只在技术理论上有意义。


四、公用继承

基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可访问。

派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。

通过派生类的对象只能访问基类的public成员。

派生类的对象可以通过调用基类的公有成员函数访问基类的私有成员一一打通了派生类访问基类私有成员的消息通道。

 1) 通过调用基类的公有成员函数访问——直接消息通道

     格式:派生类对象. 基类公有成员函数名( )

       或:派生类对象.基类名::基类公有成员函数名( );

 2) 通过调用派生类公有成员函数,在公有成员函数中

    调用基类的公有成员函数访问。     ——间接消息通道

  格式:派生类对象->派生类公有成员函数->基类公有成

              员函数->基类私有成员                           

             

 五、私有继承

基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可访问。
在派生类中“私有化”,不能再继承,但在当前类内还可用。
派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象不能访问基类中的任何成员。

派生类的对象不能访问基类的任何成员(公有成员在派生类中已变为私有,不能被对象访问)——隔断了派生类对象访问基类私有数据成员的消息通道;

但在私有继承下可以在派生类中设置专门的成员函数调用基类的公有成员函数,通过其访问基类的私有成员。

私有继承方式下,派生类对象访问基类私有成员的消息通路:

 派生类对象->派生类公有成员函数->基类公有成员函数->基类私有成员                              

                                                                                —— 间接消息通道。

访问保护成员:

派生类对象->派生类公有成员函数->基类保护成员

                                                                        —— 间接消息通道。

 六、保护成员和保护继承

基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可访问。
派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。通过派生类的对象不能访问基类中的任何成员。

 protected 成员的特点与作用

1.对建立其所在类对象的模块来说(水平访问时),它与 private 成员的性质相同。

2.对于其派生类来说(垂直访问时),它与 public 成员的性质相同。

3.既实现了数据隐藏,又方便继承,实现代码重用。        

七、派生类成员的访问属性

同名隐藏

——非virtual,同名同参或不同参

——virtual 同名不同参(同参就覆盖了)

派生类定义了与基类同名的成员时,称派生类成员隐藏了基类的同名成员

若在在派生类中使用基类的同名成员时,显式地使用类名限定符

            类名 :: 成员

class base
{
public:
	int a, b;

};
class derive :public base
{
public:
	int b, c;
};
int main()
{
	derive d;
	d.a = 1;
	d.base::b = 2;//s使用base类的b
	d.b = 3;//使用derive类的b
	d.c = 4;
	return 0;
}

派生类中的静态成员

基类定义的静态成员,不受继承方式的影响,在整个类层次体系中都可以访问。

派生类中访问静态成员,必须用以下形式显式说明

          类名 :: 成员

三种继承方式之间的比较

 多级派生时的访问属性

多级派生:每一个派生类又可以作为基类,再派生出新的派生类。

 特点:
1.无论采用何种继承方式得到的派生类,在派生类中不能访问基类的私有成员,私有成员只能被本类的成员函数访问。
2.如果在多级派生时都采用公有继承方式,直到最后一级派生类都能访问基类的公用成员和保护成员。

八、派生类的构造函数和析构函数

在定义派生类时,派生类并没有把基类的构造函数和析构函数继承下来。因此,对继承的基类成员初始化的工作要由派生类的构造函数承担,同时基类的析构函数也要被派生类的析构函数来调用。在创建派生类的对象时,由于派生类的对象包含了基类的数据成员.因此派生类的构造函数除初始化其自身定义的数据成员外.还必须对基类中的数据成员进行初始化。即派生类的构造函数要负责调用基类的构造函数。

单继承派生类的构造函数

单继承派生类构造函数的定义:

在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被初始化。

定义形式为:

派生类构造函数名(总形参表):基类构造函数名(参表

{

        派生类新增数据成员初始化语句

}

说明:
1.总形参表包含基类构造函数的参数和派生类新增的数据成员。

2.基类构造函数名(实参表)是调用基类构造函数,而派生类新增加的数据成员可以在派生类初
初始化,也可以在派生类初始化函数体中初始化。

在建立对象时,派生类构造函数的执行顺序:

①在执行派生类构造函数时,先调用基类构造函数;
②再执行派生类构造函数;

#include<iostream>
using namespace std;
#include<string>

class student
{
public:
	student(int n, string m, float s)
	{
		num = n; name = m; score = s;
	}
protected:
	int num; string name; float score;
};
class student1 :public student
{
public:
	student1(int n, string m, float s, int a, string sub) :student(n, m, s)
	{
		age = a; subject = sub;
	}
	void display();
private:
	int age;
	string subject;
};
void student1::display()
{
	cout << "num:" << num << endl;
	cout << "name:" << name << endl;
	cout << "score:" << score << endl;
	cout << "age" << age << endl;
	cout << "subject:" << subject << endl;
}
int main()
{
	student1 stu(101, "zhangsan", 86, 18, "jisuanji");
	stu.display();
	return 0;
}

有子对象的派生类的构造函数

类中的数据成员可以是类对象,类对象中的内嵌对象称为子对象,即对象中的对象

说明:

如果类A史有类B的子对象,类B有默认构造函数,或者参数全是默认参数的构造函数,或者有无参数的构造函数,那么类A的构造函数中可以不用显式初始化子对象。编译器总是会自动调用B的构造函数进行初始化。
也可以在一个类的构造函数中显式地初始化其子对象,初始化式只能在构造函数初始化列表中。

派生类中含有对象时构造函数的定义形式:

    派生类构造函数名(总参表): 基类构造函数名(参表)

     对象名(参表)

       派生类新增数据成员初始化语句   }

在建立对象时,构造函数的调用顺序为

调用基类构造函数,对基类数据成员初始化

调用子对象构造函数,对子对象数据成员初始化

执行派生类构造函数,对派生类数据成员初始化

多层派生时的构造函数

一个类不仅可以派生出一个派生类,派生类还可继续派生,形成派生的层次结构。

和派生类的构造函数的表示

   构造函数名(参数表)  

           {  函数体   }

   派生1构造函数名(参数表): 基类构造函数名(参数表)   

           派生类新增数据成员初始化语句   }

   派生类2构造函数名(参数表): 派生类1构造函数名(参数表)   

        {  派生类新增数据成员初始化语句   }

说明:在不要列出每一层派生类的构造函数,只须写出其上一层的构造函数。

在建立对象时,构造函数的调用顺序为:

  在创建派生类2对象时,调用派生类2构造函数

  在执行派生类2构造函数先调用派生类1构造函数

  在执行派生类1构造函数时,先调用类构造函数

  • 43
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值