继承
我们需要掌握以下知识点:
1.什么是继承?
2.继承权限和访问限定符
3.在public继承权限下,理解赋值兼容规则
4.继承中的作用域,理解什么是同名隐藏
5.派生类的默认成员函数
6.继承与友元
7.继承与static静态变量
8.继承体系下派生类的对象模型
什么是继承呢?
在C++中,所谓“继承”就是在一个已存在的类的基础上建立一个新的类。已存在的类称为“基类”或者“父类”
新建立的类称为“派生类”或者“子类”。
一个新类从已有的类那里获得其已有特性,称为类的继承。
从已有的类(父类)产生一个新的子类。称为类的派生。
拿生活中的例子来说,相当于说,你爸现在有两个矿场,你未来会从你爸手里接过矿场,即你继承了你爸的财产,你在未来会在此财产的基础上,继续发展,获得更多的财富。就这样,子子孙孙,无穷尽也。
关于继承权限和访问限定符
需要注意一下几点:
1.基类的private成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中被访问,就定义为protected。
可以看出保护成员限定符是因继承才出现的。
2.public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象,即:在所有用到基类对象的位置,都可用子类对象来代替。
3.无论哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能被访问)
4.使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
5.在实际运用中一般都是public继承。
在public继承权限下,理解赋值兼容规则
在public继承权限下,子类和派生类对象之间有:
1.子类对象可以赋值给父类对象(切割)
2.父类对象不能赋值给子类对象
3.父类的指针/引用可以指向子类对象(******)
4.子类的指针/引用不能指向父类对象(可以通过强制类型转换完成,但可能会发生程序崩溃)
注意一下:根据对象模型的概念有助于理解赋值兼容原则:类中成员变量在内存中的布局形式。
继承中的作用域,理解什么是同名隐藏
1.在继承体系中,基类和派生类是两个不同的作用域
2.子类和父类有同名成员,子类成员将屏蔽父类对成员的直接访问(即同名隐藏)也就是说,用派生类对象去访问继承体系中的同名成员,只能访问到派生类自己的,基类的成员无法访问到,但是可以通过基类::基类成员 去访问。
派生类的默认成员函数
派生类继承了父类,那么会继承父类的六大默认成员函数吗?
1.构造函数:
派生类不会继承父类的构造函数!
派生类的构造函数属于合并构造函数,就是说他在执行自身的构造函数前,会先调用基类的构造函数完成它继承的基类成员的初始化,虽然你继承基类的成员,但是人家的成员初始化你得交给人家基类去做。所以说派生类执行自身的构造函数前,会先调用其基类的构造函数,如果他的基类还有父类,那么又先去调用基类的父类的构造函数,直到没有父类为止。这个调用构造函数的方式可以形象的看成一条链,也称为构造函数链。
派生类中如果没有定义构造函数,编译器会自动生成一个默认构造函数。但是当父类的构造函数是有参、而子类没有显示调用父类的构造函数时,就会出错,所以建议一般将构造函数都写成缺省的方式,并且在子类中显示的去调用父类的构造函数。
2.析构函数:
析构函数和构造函数恰好相反,会先调用子类的析构函数,再去调用父类的构造函数。注意:析构函数不用显示的去调用父类的析构函数,它会自己去调用父类的析构,不想构造函数那样需要显示的去调用父类的。
3.拷贝构造函数:
拷贝构造函数也是构造函数,是特殊的构造函数,所以它也不会被继承,并且先调用父类的构造函数,再调用子类的拷贝构造
继承与友元
友元关系不能继承,因为友元类不是类的成员,也就是说,基类友元不能访问。
继承与static静态变量
继承体系下派生类的对象模型
1.单继承
对象模型如图所示:
2.多继承
3.菱形继承
菱形继承 = 单继承 + 多继承
其对象模型为:
菱形继承存在二义性,无法区分访问的是C1还是C2的_b,如何解决?
在当前,只有一种方法,就是加上作用域限定符。当然,下面介绍的菱形虚拟继承也可以很方便的解决这个问题。
4.虚拟继承
虚拟继承就是在基类前面加上virtual
class B//父类
{
}
class D: virtual public B//虚拟继承派生类
{
}
5.菱形虚拟继承(重要)
派生类对象模型
注意:对比虚拟继承&单继承
1.多出4个字节---地址---偏移量表格
2.派生类对象模型:基类在下,派生类在上
3.派生类对象访问基类成员--->通过偏移量表格地址
4.合并构造函数,并且多传递 '1'--->检测是否为虚拟继承
在构造对象期间,将偏移量表格的地址放在对象的前四个字节。
总结常见题型:
1.什么是继承?
2.什么是菱形继承?菱形继承有什么缺陷?
3.什么是菱形虚拟继承?为什么使用菱形虚拟继承可以解决菱形继承存在的问题?
4.继承体系中,基类哪些成员被派生继承了?友元可以继承吗?
5.设计一个类,该类不能被继承(思路:私有构造方法+静态成员函数)
注意:在C++11中,还可以使用final关键字来达到效果。
6.用C语言模拟实现继承
上一篇: 继承
下一篇: 【Qt】断言Q_ASSERT的使用