作者:良知犹存
转载授权以及围观->欢迎添加Wx:Allen-Iverson-me-LYN
前言:本文为C++使用过程中的一些细节知识补充,碎片化的知识.其中有韦东山老师和其他博主一些知识笔记,在此谢谢韦老师以及各博主的文章博客,受益良多.
一、基类成员在派生类中的访问控制属性:
首先派生类是C++中引入派生类,是为了解决重复代码的问题,通过使用派生类,程序员只需要在已经存在的类中进行继承,只需要修改少量的代码就产生新的类.
但是继承的时候,因为类成员所属的限定符不同,所以导致继承的时候,访问属性不同.
下面我们先来描述一下类的三种成员:
- public (公共成员) ,顾名思义在public限定下的类成员可以被类里面的成员函数引用,亦可以类之外的其他函数引用.所以在继承类,public成员可以完整属性的被继承.
- private(私有成员),特指在类中私用的成员,一般为类的数据成员.这些数据成员一般会被在public的成员函数进行访问.所以私有成员只能被定义的类的成员函数进行引用,其他类无法进行访问,此处友员类或者友员函数除外.
- protect(受保护的成员),此限制符下的成员访问属性介于public与private之间.protect标识成员不能被类外访问,但可以通过继承的派生类进行访问.
类的几种访问限制符了解完,下面开始介绍继承中我们继承成员的具体访问情况.
- 第一种public继承,由于public是公开的特性,类之外也可以被引用,所以当派生类继承为public,private或者protect,public下面的成员会随着派生类的限定符进行划归,也就是继承到public就是public成员,继承到protect就是protect成员,继承到private就是private成员.
- 第二种protect继承,由于继承父类中该成员就是属于protect所以派生的子类也会受到限制,该成员由于父类已经进行限制,所以继承的子类到public是无法完整获得任意访问的属性,所以如下图,继承到public中的protect成员依旧有protect的属性限制,继承到protect和private限制的时候,类成员按照子类的限制符进行访问。
- 第三种private继承,由于private成员是最私密的限制,所以继承之后全部为private的权限。
综上所述,我们发现,继承的时候该成员是按照继承的父类以及继承到的子类的成员限制最大的类型进行继承的。
继承示例:
class D{......}; class B: public D{......};
注:继承的时候如果不写public默认就会私有继承。
二、虚拟继承
多重继承容易出现多义,另外多重继承中出现环继承,也为了节省内存空间,所以C++引入虚拟继承。
多重继承多义性的代码片段,参考代码韦东山C++
#include <iostream> #include <string.h> #include <unistd.h> /*多态*/ using namespace std; class Human{ private: int a; public: void eating(void){ cout<<"use hand to eat"<<endl; } }; class Englishman : public Human{ public: void eating(void){ cout<<"use knife to eat"<<endl; } }; class Chinese : public Human{ public: void eating(void){ cout<<"use chopsticks to eat"<<endl; } }; void test_eating(Human &h) { h.eating(); } int main(int argc,char **argv) { Human h; Englishman e; Chinese c; test_eating(h); test_eating(e); test_eating(c); cout<<"Humen length:="<<sizeof(h)<<endl; cout<<"Englishman length:="<<sizeof(e)<<endl; cout<<"Chinese length:="<<sizeof(c)<<endl; return 0; }
多重继承使得程序出现二义性,可以用virtual进行虚拟继承来解决,但是由于多重继承会使程序变得复杂,所以不建议使用多重继承。
#include <iostream> #include <string.h> #include <unistd.h> /*多态*/ using namespace std; class Human{ private: int a; public: virtual void eating(void){ cout<<"use hand to eat"<<endl; } ~Human(){ cout<<"~Human()"<<endl; } }; class Englishman : public Human{ public: void eating(void){ cout<<"use knife to eat"<<endl; } ~Englishman(){ cout<<"~Englishman()"<<endl; } }; class Chinese : public Human{ public: void eating(void){ cout<<"use chopsticks to eat"<<endl; } ~Chinese(){ cout<<"~Chinese()"<<endl; } }; void test_eating(Human &h) { h.eating(); } int main(int argc,char **argv) { Human h; Englishman e; Chinese c; test_eating(h); test_eating(e); test_eating(c); cout<<"Humen length:="<<sizeof(h)<<endl; cout<<"Englishman length:="<<sizeof(e)<<endl; cout<<"Chinese length:="<<sizeof(c)<<endl; return 0; }
环装继承:
class A{......}; class B: public A{......}; class C: public A{......}; class D: public B, public C{.....};
class A class B:public virtual A; class C:public virtual A; class D:public B,public C;
降低内存使用的实际原理:虚拟基类中的构造函数只执行一次。并且构造的时候虚拟基类先执行。
using namespace std; class Human { private: int a; public: virtual void eating(void) { cout<<"use hand to eat"<<endl; } virtual ~Human() { cout<<"~Human()"<<endl; } }; class Englishman : public Human { public: void eating(void) { cout<<"use knife to eat"<<endl; } virtual ~Englishman() { cout<<"~Englishman()"<<endl; } }; class Chinese : public Human { public: void eating(void) { cout<<"use chopsticks to eat"<<endl; } virtual ~Chinese() { cout<<"~Chinese()"<<endl; }/*析构函数也应该为虚拟函数*/ }; void test_eating(Human h){ h.eating(); } int main(int argc, char **argv){ Human* h = new Human; Englishman* e = new Englishman; Chinese* c = new Chinese; Human *p[3] = {h, e, c}; int i; for (i = 0; i < 3; i++) { p[i]->eating(); delete p[i]; } return 0; }