
目录C 继承的基本概念继承类型对比表继承类模板继承中的作⽤域基类和派⽣类间的转换派生类默认成员函数继承与友元多继承及其菱形继承问题C多继承及其菱形继承问题解析无代码多继承核心概念菱形继承问题解决方案虚继承IO库中应用继承和组合C 继承的基本概念继承是面向对象编程OOP的核心特性之一允许一个类派生类也可以叫子类基于另一个类基类也可以是父类构建继承其成员变量和成员函数。C 支持多种继承方式包括单继承、多继承和虚继承。继承类型对比表继承类型基类 public 成员在派生类中的访问权限基类 protected 成员在派生类中的访问权限基类 private 成员在派生类中的访问权限公有继承publicprotected不可直接访问保护继承protectedprotected不可直接访问私有继承privateprivate不可直接访问这个表可以不用记以最小权限为访问权限:public protected private ,其中class的继承可以不写private,class默认就是private,则struct默认就是public。如果是private派生类无法访问基类protected派生类可以访问但是类外访问不了public就都可以访问。class person { public: person(const std::string name1,const std::string ID,const std::string add ) :name(name1), ID_card(ID), address(add) { } protected: std::string name; std::string ID_card; std::string address; }; class my_form :public person { public: my_form(const std::string name1, const std::string ID, const std::string add, const std::string work1) :person(name1,ID,add), work(work1) { } void Date() { std::cout 名字: name std::endl; std::cout 身份证: ID_card std::endl; std::cout 地址: address std::endl; std::cout 工作: work std::endl; } private: std::string work; }; int main() { my_form i(张三, 12345, 广东, 学生); i.Date(); return 0; }继承类模板类模板和继承——这种继承耦合性高没有组合好我们可以创建可以操作多种数据类型的基类并通过继承机制扩展这些类的功能。这在实现通用数据结构如链表、树等或编写与类型无关的算法时特别有用。#includevector templateclass T class stack :protected std::vectorT// stack和vector的关系既符合is-a也符合has-a { public: void push(const T x) { std::vectorT::push_back(x); } void pop() { std::vectorT::pop_back(); } T top() { return *(std::vectorT::end()-1); } size_t size() { return std::vectorT::size(); } bool empty() { return std::vectorT:: empty(); } };继承中的作⽤域隐藏规则1. 在继承体系中基类和派⽣类都有独⽴的作⽤域。2. 派⽣类和基类中有同名成员派⽣类成员将屏蔽基类对同名成员的直接访问这种情况叫隐藏。 在派⽣类成员函数中可以使⽤基类::基类成员显⽰访问3. 需要注意的是如果是成员函数的隐藏只需要函数名相同就构成隐藏。4. 注意在实际中在继承体系⾥⾯最好不要定义同名的成员。class A { public: void f() { std::cout A::f() std::endl; } int a; }; class B : public A { public: void f(int a) { std::cout B::f() std::endl; } int a; }; int main() { B b; b.f(1); b.A::f(); //b.f()这样子会编译报错 return 0; }基类和派⽣类间的转换基类和派生类之间的转换主要有三种方式指针转换、引用转换和对象拷贝。指针和引用转换是隐式的并且只能访问派生类对象中的基类部分成员对象拷贝会进行切片操作只保留派生类对象中的基类部分成员。这些转换在多态性和继承机制中起着重要作用但也需要注意切片可能带来的信息丢失问题。派生类默认成员函数这里的构造跟普通构造差不多如果没有写构造就是编辑器默认构造如果自己写了构造编辑器不生成构造如果加了default就会产生默认构造其中初始化列表也是一样的。继承的基类父类必须要在自己类里面写默认构造在子类写会报错调用默认构造可以看上面代码。继承与友元基类友元无法访问派生类对象还比于父亲的朋友不一定是我朋友所以继承不了友元class B; class A { public: friend void Print__AB(const A a,const B b); protected: int _a; }; class B : public A { protected: int _b; }; void Print__AB(const A a,const B b) { std::cout a._a b._b std::cout;//这里会编译器报错访问不了_b. }继承与静态成员基类定义了static静态成员则整个继承体系⾥⾯只有⼀个这样的成员。⽆论派⽣出多少个派⽣类都 只有⼀个static成员实例。class A { public: void _apush1() { _a; } protected: static int _a; }; int A::_a 0; class B : public A { public: int a_size() { return _a; } protected: int _b; }; int main() { A y; B x; y._apush1(); x._apush1(); std::coutx.a_size()std::endl;//输出2 return 0; }多继承及其菱形继承问题C多继承及其菱形继承问题解析无代码多继承核心概念多继承是面向对象编程中的一种机制允许一个派生类同时从多个基类继承属性和行为基本模型派生类如同组装体整合多个基类的功能内存布局派生类对象包含所有基类的子对象按继承顺序排列典型场景设备控制器继承输入接口输出接口电源管理菱形继承问题当继承结构形成菱形时引发经典问题核心矛盾数据冗余问题B和C各自包含A的完整副本D同时继承B和C → 包含两份A的副本结果相同数据重复存储浪费内存访问二义性问题当D访问A的成员时编译器无法确定应通过B路径还是C路径访问结果编译错误ambiguous access解决方案虚继承通过virtual关键字重构继承关系class B : virtual public A {...}; class C : virtual public A {...}; class D : public B, public C {...};虚继承的魔法共享基类机制B和C不再包含完整A副本改为存储指向共享A的指针虚基表指针派生类主导构造最底层派生类D直接构造虚基类A中间类B/C不触发A的构造访问统一化所有路径指向同一A实例彻底消除二义性IO库中应用继承和组合特性继承Inheritance组合Composition关系语义是一个is-a有一个has-a耦合度紧耦合父子绑定松耦合部件独立生命周期同生共死自主控制访问权限直接访问基类protected成员仅通过接口访问典型类比家族血脉传承汽车组装零件 注意尽量使用组合低耦合关联性低比较好