前言
学习三大特性之继承
一. 什么是继承(代码复用性)
继承是类与类之间的一种关系,即子类继承父类的特征和行为,使得子类具有和父类相同的属性和行为。
继承的好处在于子类继承了父类的属性和方法从而实现了代码的复用。
二.面向对象的基本特征
-
继承后基类成员的访问权限
各种继承方式和类成员访问权限组合后情况如下:
总结:基类private成员无论以什么方式继承到派生类中都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
基类private成员在派生类中不能被访问,如果基类成员不想在派生类外直接被访问,但需要在派生类中访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
上面的表格看起来复杂,实际上归纳一下就会发现:基类的私有成员在子类都是不可见;基类的其他成员在子类的访问方式就是访问限定符和继承方式中权限更小的那个(权限排序:public>protected>private)。
使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,但最好显式地写出继承方式。
在实际使用时一般都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,扩展和维护性不强。
三.派生类的默认成员函数
和类中的默认成员函数差不多,需要注意的是如果需要友元函数的话需要提前声明,因为友元函数不能被继承。
四.深拷贝和浅拷贝
浅拷贝(默认拷贝函数):将原对象或原数组的引用直接赋给新对象,新数组,新对象/新数组只是原对象的一个引用。
深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是引用深拷贝会在堆内存中另外申请空间来储存数据,从而解决了指针悬挂问题。当数据成员中有指针,必须要用深拷贝
***********
数据成员中含有指针时,必须用深拷贝
当用浅拷贝时,新对象的指针与原对象的指针指向了堆上的同一块儿内存,新对象和原对象析构时,新对象先把其指向的动态分配的内存释放了一次,而后原对象析构时又将这块已经释放过的内存再释放一次。对同一块动态内存执行2次以上释放的结果是未定义的,所有会导致内存泄漏或程序崩溃。
所以需要深拷贝来解决问题,当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象开辟一块新的资源,而不再对拷贝对象中对其他资源的引用的指针或引用进行单纯的赋值。
总结
学习继承的三种继承方式,并且掌握深拷贝与浅拷贝。