继承与静态成员变量基类定义了static静态成员则整个继承体系⾥⾯只有⼀个这样的成员。⽆论派⽣出多少个派⽣类都只有⼀个static成员实例。classPerson{public:string _name;staticint_count;};intPerson::_count0;classStudent:publicPerson{protected:int_stuNum;};intmain(){Person p;Student s;// 这⾥的运⾏结果可以看到⾮静态成员 _name 的地址是不⼀样的// 说明派⽣类继承下来了⽗派⽣类对象各有⼀份coutp._nameendl;couts._nameendl;// 这⾥的运⾏结果可以看到静态成员 _count 的地址是⼀样的// 说明派⽣类和基类共⽤同⼀份静态成员coutp._countendl;couts._countendl;// 公有的情况下⽗派⽣类指定类域都可以访问静态成员coutPerson::_countendl;coutStudent::_countendl;return0;}可以看到基类中定义的static成员变量在基类自己那和派生类都是同一个地址而指定类域对象count值和指定派生类类域count值相同能证明static静态成员变量在基类和派生类都是公用一个地址多继承单继承⼀个派⽣类只有⼀个直接基类时称这个继承关系为单继承多继承⼀个派⽣类有两个或以上直接基类时称这个继承关系为多继承多继承对象在内存中的模型是先继承的基类在前⾯后⾯继承的基类在后⾯派⽣类成员在放到最后⾯。classPerson{public:string _name;// 姓名};classStudent:publicPerson{protected:};int_num;//学号classTeacher:publicPerson{protected:int_id;// 职⼯编号};classAssistant:publicStudent,publicTeacher{protected:string _majorCourse;// 主修课程};intmain(){// 编译报错error C2385: 对“_name”的访问不明确Assistant a;a._namepeter;// 需要显⽰指定访问哪个基类的成员可以解决⼆义性问题但是数据冗余问题⽆法解决a.Student::_namexxx;a.Teacher::_nameyyy;return0;}多继承的语法就如上图的代码派生类的基类也会有它的基类上面的意思是我假设为博士生我可能是某科院长的学生我还可以是某主修课程的老师我这两个身份的我的真实名字是我这两个身份公共的所以我定义一个Person作为它们的基类然后你照着写的话然后调试窗口看一下创建的对象会发现同一个对象有两个Person类一个是student中的一个是teacher中的我不管是什么身份我的名字都是同一个所以这就导致数据冗余还有你如果这样写:Assistant a;a._namepeter;会报错编译器会报不知道指定哪一个_name,因为你Assistant中继承的student和teacher中都有继承Person的_name,所以编译器才会报这个错误这就是二义性所以在这里可以把name定义为Assistant的私有成员只是这样违背了实际生活这种情况是多继承的特殊情况:菱形继承菱形继承菱形继承菱形继承是多继承的⼀种特殊情况。菱形继承的问题从下⾯的对象成员模型构造可以看出菱形继承有数据冗余和⼆义性的问题在Assistant的对象中Person成员会有两份。⽀持多继承就⼀定会有菱形继承像Java就直接不⽀持多继承规避掉了这⾥的问题所以实践中我们也是不建议设计出菱形继承这样的模型的所以要解决数据冗余和二义性的话就要引出下面的知识: 虚继承虚继承很多⼈说C语法复杂其实多继承就是⼀个体现。有了多继承就存在菱形继承有了菱形继承就有菱形虚拟继承底层实现就很复杂性能也会有⼀些损失所以最好不要设计出菱形继承。多继承可以认为是C的缺陷之⼀后来的⼀些编程语⾔都没有多继承如Java。语法就是在会产生冗余的类加上virtual,比如在上面案例中Student和Teacher里都有Person的成员那就在它们继承Person中加vitrualclassPerson{public:Person(constchar*name):_name(name){}string _name;// 姓名};classStudent:virtualpublicPerson{public:Student(constchar*name,intnum):Person(name),_num(num){}protected:int_num;//学号};classTeacher:virtualpublicPerson{public:Teacher(constchar*name,intid):Person(name),_id(id){}protected:int_id;// 职⼯编号};只看创建类的名称那就是增加了virtual,里面的构造和单继承是一样的那Assistant的构造有点不一样我先写出来引出个题来然后再解答a对象的名字最终是什么?classAssistant:publicStudent,publicTeacher{public:Assistant(constchar*name1,constchar*name2,constchar*name3,intnum,intid,constchar*majorCourse):Person(name3),Student(name2,num),Teacher(name1,id),_majorCourse(majorCourse){}protected:string _majorCourse;// 主修课程};intmain(){Assistanta(张三,李四,王五,25565,1005,计算机工程);这里的答案是名字最后是王五原因: 这里编译器做了特殊处理在构造函数中虽然你写了派生类Assistant在各个基类中构造基类它们自己的成员但是它不会走它们构造的Person()这个初始化列表中的只会走student和teacher它的基类Person中的构造去构造name,这也是为什么在Assistant中多了额外要写的Persona._namepeter;a.Student::_namexxx;a.Teacher::_nameyyy;而且这里改的话在调试窗口中student和teachet中的name都会改就证明虚继承中是公用一个继承的基类成员所以虚继承的特点1.在这里的Assistant中的student和teacher中的Person是指针偏移量或指针(具体看编译器如何处理)2. 如果是student和teachet的对象那构造函数会正常走它的基类的整体构造后面我再写的多态会很好体现