多层继承与多重继承

📅 2026/7/12 19:27:13
多层继承与多重继承
多层继承与多重继承一、概念对比继承类型定义语法关系描述多层继承多个类逐级继承形成继承链class B : public Aclass C : public B父类 → 子类 → 孙子类多重继承一个类同时继承多个基类class C : public A, public B一个子类有多个直接父类二、多层继承链式继承2.1 定义与内存布局classObject{private:intoa;// 4Bprotected:intob;// 4Bpublic:intoc;// 4Bvoidfun_oa(intx){oax;}};classBase:publicObject{// 第1层Base 继承 Objectprivate:intbx;// 4Bprotected:intby;// 4Bpublic:intbz;// 4B};classTest:publicBase{// 第2层Test 继承 Baseprivate:intta;// 4Bprotected:inttb;// 4Bpublic:inttc;// 4B};// sizeof(Object) 12 字节 (oaoboc)// sizeof(Base) 24 字节 (Object的12 bxbybz)// sizeof(Test) 36 字节 (Base的24 tatbtc)// 构造顺序Object → Base → Test │// 析构顺序Test → Base → Object多层继承的内存布局 :2.2 多层继承的成员访问classTest:publicBase{public:voidfun_t(){// 访问自己的成员tatbtc0;// 可以// 访问直接基类 Base 的成员by1;// 可以Base 的 protected 成员bz1;// 可以Base 的 public 成员// bx 1; // × 错误Base 的 private 成员// 访问间接基类 Object 的成员ob2;// 可以Object 的 protected 成员oc2;// 可以Object 的 public 成员// oa 2; // 错误Object 的 private 成员// 调用间接基类的方法fun_oa(12);// 可以继承自 Object 的 public 方法}};2.3 多层继承中的访问级别汇总// 基类classObject{private:intoa;protected:intob;public:intoc;};// 第1层public 继承classBase:publicObject{// 继承后ob 仍为 protectedoc 仍为 public};// 第2层public 继承classTest:publicBase{// 可以访问ob, oc// 不能访问oa};三、多重继承3.1 定义与内存布局classObjectA{private:inta1;protected:inta2;public:inta3;};classObjectB{private:intb1;protected:intb2;public:intb3;};// 多重继承同时继承 ObjectA 和 ObjectBclassTest:publicObjectA,publicObjectB{private:intt1;protected:intt2;public:intt3;};// sizeof(Test) sizeof(ObjectA) sizeof(ObjectB) sizeof(Test自身)3.2 多重继承的成员访问classTest:publicObjectA,publicObjectB{public:voidfun_t(){// 访问自己的成员t1t2t30;// 可以// 访问 ObjectA 的成员a21;// 可以ObjectA 的 protected 成员a31;// 可以ObjectA 的 public 成员// 访问 ObjectB 的成员b22;// 可以ObjectB 的 protected 成员b32;// 可以ObjectB 的 public 成员}};3.3 菱形继承问题二义性// 菱形继承问题classObject{public:intvalue;};classBaseA:publicObject{};classBaseB:publicObject{};// 菱形继承Test 包含两份 Object 的副本classTest:publicBaseA,publicBaseB{public:voidfun(){// value 10; // × 二义性错误不知道是 BaseA::value 还是 BaseB::valueBaseA::value10;// 指定使用 BaseA 的 valueBaseB::value20;// 指定使用 BaseB 的 value}};菱形继承内存布局(见 多重继承与菱形继承)3.4 虚继承解决菱形继承// 虚继承解决菱形继承问题classObject{public:intvalue;};classBaseA:virtualpublicObject{};// 虚继承classBaseB:virtualpublicObject{};// 虚继承classTest:publicBaseA,publicBaseB{public:voidfun(){value10;// 正确只有一份 Object 副本}};虚继承内存布局(见 多重继承与菱形继承)四、private 继承对多层继承的影响4.1 核心概念private 继承是一种“实现继承”它将基类的所有成员无论原来是 public 还是 protected都变为派生类的 private 成员。这会对后续的继承链产生“阻断”效应。4.2 private 继承的成员访问变化4.2.1 单层 private 继承的访问变化classObject{private:intoa;// 私有成员protected:intob;// 保护成员public:intoc;// 公有成员voidfun_oa(intx){oax;}};classBase:privateObject{// 继承后Object 中的所有成员在 Base 中都变为 private// - oa: 仍然 private本来就不可访问// - ob: 从 protected 变为 private// - oc: 从 public 变为 private// - fun_oa(): 从 public 变为 privateprivate:intbx;protected:intby;public:intbz;voidfun(){// 在 Base 内部仍然可以访问虽然变成了 privatefun_oa(12);// 可以调用在类内部ob2;// 可以访问在类内部oc3;// 可以访问在类内部bxbybz0;}};intmain(){Base base;// 错外部无法访问任何从 Object 继承来的成员// base.oc 10; // 错误oc 在 Base 中是 private// base.ob 20; // 错误ob 在 Base 中是 private// base.fun_oa(30); // 错误fun_oa 在 Base 中是 private// 只能访问 Base 自己的 public 成员base.bz100;// 正确return0;}4.2.2 访问变化总结表Object 中的成员原始访问级别经过 private 继承后在 Base 中的访问级别oaprivate不可访问private 永远不可继承obprotectedprivate被降级ocpublicprivate被降级fun_oa()publicprivate被降级4.3 private 继承对后续继承链的影响4.3.1 阻断效应当Base以private方式继承Object后Test类无论以何种方式继承Base都无法访问Object的成员。classObject{private:intoa;protected:intob;public:intoc;voidfun_oa(intx){oax;}};classBase:privateObject{// Object 的所有成员在 Base 中都变成了 privateprivate:intbx;protected:intby;public:intbz;voidfun(){// Base 内部可以访问fun_oa(12);ob2;oc3;}};// Test 以 public 方式继承 BaseclassTest:publicBase{private:intta;protected:inttb;public:inttc;voidfun_t(){// 可以访问 Base 自己的成员tatbtc0;by1;// Base::by 是 protectedTest 可以访问bz1;// Base::bz 是 publicTest 可以访问// 错误 无法访问从 Object 继承来的成员// ob 2; // 错误ob 在 Base 中是 private// oc 2; // 错误oc 在 Base 中是 private// fun_oa(12); // 错误fun_oa 在 Base 中是 private}};intmain(){Test test;// 可以访问 Test 自己的 public 成员test.tc100;// 可以访问 Base 的 public 成员如果 Test 是 public 继承test.bz200;// 错误 无法访问任何 Object 的成员// test.oc 300; // 错误oc 已被 Base 私有化// test.ob 400; // 错误// test.fun_oa(500); // 错误test.fun_t();// 可以调用test.fun();// 可以调用Base 的 public 方法return0;}4.3.2 阻断效应的图解五、不同继承方式对后续继承的影响对比5.1 场景一Base 以 public 继承 ObjectclassBase:publicObject{// Object 的 public → Base 中 public// Object 的 protected → Base 中 protected};classTest:publicBase{// Test 可以访问 Object 的 public 和 protected 成员voidfun(){oc10;// 可以Object::oc 仍为 publicob20;// 可以Object::ob 仍为 protected}};5.2 场景二Base 以 protected 继承 ObjectclassBase:protectedObject{// Object 的 public → Base 中 protected// Object 的 protected → Base 中 protected};classTest:publicBase{// Test 可以访问 Object 的 public 和 protected 成员// 因为它们都变成了 Base 的 protectedvoidfun(){oc10;// 可以Object::oc 在 Base 中变为 protectedob20;// 可以Object::ob 在 Base 中仍为 protected}};intmain(){Test test;// test.oc 10; // × 外部不能访问oc 在 Base 中变成了 protectedreturn0;}5.3 场景三Base 以 private 继承 ObjectclassBase:privateObject{// Object 的所有成员 → Base 中 private};classTest:publicBase{// × Test 无法访问 Object 的任何成员voidfun(){// oc 10; // 错误oc 在 Base 中是 private// ob 20; // 错误ob 在 Base 中是 private}};5.4 三种继承方式对比总结5.4.1 继承方式对成员访问的影响总结基类成员public 继承protected 继承private 继承public派生类中为 public派生类中为 protected派生类中为 privateprotected派生类中为 protected派生类中为 protected派生类中为 privateprivate派生类中不可访问派生类中不可访问派生类中不可访问关键点private 继承会阻断后续继承链对基类成员的访问。Base 对 Object 的继承方式Object 成员在 Base 中的级别Test 能否访问 Object 成员外部能否通过 Base 访问 Object 成员public 继承public → publicprotected → protected可以public/protected可以public 成员protected 继承public → protectedprotected → protected可以都变成 protected不可以private 继承全部变为 private不可以不可以六、多层继承 与 多重继承对比特性多层继承多重继承基类数量只有一个直接基类有多个直接基类继承深度可以很深链式通常较浅内存布局线性叠加多个基类子对象并列二义性问题通常无可能有如菱形继承虚继承需求不需要菱形继承时需要复杂性较低较高使用场景层次分类如 Person→Student→Graduate功能组合如 FlyingCar 继承 Car 和 Plane七、选择建议场景推荐方案原因表示层次分类关系多层继承如 Person → Student → Graduate表示功能组合多重继承如 FlyingCar 同时具备飞行和驾驶功能接口实现多重继承纯虚类C 的多重继承可实现类似接口的功能避免菱形继承虚继承确保公共基类只有一份副本大多数情况优先考虑多层继承更简单更不容易出错