c++ primer(六)

继承是面向对象程序设计的基本特性之一,是从已有的类的基础上建立新的类。

继承性是面向对象程序程序设计支持代码重用的重要机制。

面向对象程序设计的集成机制提供了无限重复利用程序资源的一种途径。

通过C++语言中 的继承机制,一个新类既能共享另一个类的操作和数据,也可以在新类中定义已有类中没有的成员,这样就能极大的节省时间和资源


继承是类之间定义的一种重要关系。定义类B时,自动得到类A的操作和数据属性,使得程序员只需定义类A中所没有的新成分就可完成在类B中的定义。这样B继承了A,A派生了B,A是基类,B是派生类。这种机制叫做继承

派生类具有基类的特性,共享基类的成员函数,使用基类的数据成员,还可以定义自己特性(自己的数据成员和成员函数)

c++中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的称作单继承,从多个基类派生的成为多继承。

公有继承、私有继承、保护继承

公有继承,基类的公有成员和保护成员作为派生类的成员时,它们都保持着原有的状态,而基类的私有成员仍然是私有的

私有继承,基类的公有成员和保护成员作为派生类的私有成员,而且不能被这个派生类的子类访问(孙子不能继承了)

保护继承,基类的所有公有成员保护成员都成为派生类的保护成员,而且只能被它的派生类成员函数或者友元访问,基类的私有成员仍是私有的

派生类可以覆盖基类成员

派生类不能访问基类私有成员


派生类中的静态成员

不管公有派生类还是私有派生类,都不影响派生类对基类的静态成员的访问,派生类对基类静态成员必须显示的使用以下形式  类名::成员


构造函数不能被继承,c++提供一种机制,使得在创建派生类对象时, 能够调用基类的构造函数来初始化基类数据

派生类构造函数一般格式如下

<派生类名>(<派生类构造函数总参数表>):<基类构造函数>(<参数表1>),<子对象名>(<参数表2>){

<派生类数据成员初始化>

}


派生类构造函数调用顺序如下:

调用基类的构造函数,调用顺序安装他们继承时说明的顺序

调用子对象类的构造函数,调用顺序按照他们在类中说明的顺序

派生类构造函数体中的内容


由于析构函数也不能被继承,因此在执行派生类的析构函数时,基类的西沟函数也将被调用。执行的顺序是限先执行派生类的析构函数,在执行基类的析构函数,其顺序与执行构造函数时的顺序正好相反。


在多继承情况下,多个基类构造函数的调用次序是按基类在被继承时所声明的次序从左到右,依次调用,与它们在派生类的构造函数实现中的初始化列表出现的次序无关。


赋值兼容规则:在公有派生的情况下,一个派生类的对象可用于基类对象适用的地方。赋值兼容规则有三种情况:

(1) 派生类的对象可以赋值给基类的对象

derived d;

base b;

b =d;

(2) 派生类的对象可以初始化基类的引用

derived d;

bae &br = b;

(3)派生类的对象的地址可以赋值给指向基类的指针

derived d;

base *pb = &d;


虚基类

当某类的部分或全部直接是从另一个共同基类派生来的,这些直接基类中从上一级基类继承来的成员就拥有相同的名称,也就是说,这些同名的成员在内存中存在多个副本。而多数情况下,由于它们的上一级基类完全一样,而在编程时,只需使用多个副本中的任意一个

C++允许程序中是建立公共基类的一个副本,将直接基类的共同基类设置为虚基类,这时,从不同路径继承过来的该类成员在内存中只拥有一个副本,这样有关公共基类成员访问的二义性问题就不存在了


如果一个派生类C从多个基类派生B1,B2,而这些基类又有一个共同的基类A,则在对该基类中声明的名字进行访问时,会产生二义性。例如,A中有函数fun(),c的对象使用fun时,就很难搞清楚B1还是B2继承来的

引进虚基类的真正目的是为了解决二义性问题,当基类被继承时,在基类的访问控制保留字前面加上virtual来定义

如果基类被声明为虚基类,则重复继承的基类在派生类对象实例中只好存储一个副本,否则,将会出现多个成员的副本


引进虚基类后,派生类的对象中只存在一个虚基类的子对象,当一个类有虚基类时,编译系统将为该类的对象定义一个指针成员,让它指向虚基类的子对象。该指针被称为虚基类指针。

类之间的继承关系可以用一个有向无环图表示,称为类格。一个类在类格中,同名的虚基类只产生一个虚基类子对象,而每个非虚基类产生各自的子对象。虚基类的构造函数按被继承的顺序构造,建立虚基类的子对象时,虚基类的构造函数仅被调用一次。

为了初始化基类的子对象,派生类的构造函数要调用基类构造函数。对于虚基类来讲,由于派生类的对象中只有一个虚基类子对象。为保证虚基类子对象纸杯初始化一次,这个虚基类构造函数必须只被调用一次。由于继承结构的层次可能很深。规定将在建立对象时,所指定的类称为最直接派生类。

虚基类子对象是由最直接派生类的构造函数通过虚基类构造函数进行初始化的。

如果一个派生类有一个直接或间接虚基类,那么派生类的构造函数的成员列表中必须列出对虚基类构造函数的调用,如果未被列出,则表示使用该虚基类的默认构造函数来初始化派生类对象的虚基类子对象。

c++规定,在一个成员初始化列表中出现对虚基类和非虚基类构造函数的调用,则虚基类的构造函数先于非虚基类的构造函数执行。

从虚基类直接或间接继承的派生类中的构造函数的成员初始化列表中,都要列出这个虚基类构造函数的调用。但是,只有用于建立对象的那个派生类的构造函数调用虚基类的构造函数,而该派生类的基类中所列出的对这个虚基类的构造函数电泳在执行中被忽略,这样便保证了对虚基类的子对象只初始化一次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值