版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
类的继承与派生面向对象的程序设计语言——C++·第4章Contents本章目录面向对象的程序设计语言——C++第4章类的继承与派生01继承的基本概念与关系模型02单一继承与访问控制03多重继承与虚基类04派生类的构造与析构CHAPTER01继承的基本概念与关系模型从现实世界到代码世界的继承思维,理解类与类之间的层级关系Chapter04·Inheritance继承的本质:代码复用的核心机制继承是面向对象程序设计中实现代码复用的基础机制。通过在已有类(基类/父类)的基础上定义新类(派生类/子类),新类自动继承已有类的属性与行为,并可扩展新功能,避免重复编码,提升软件开发效率。自动继承——派生类自动拥有基类的全部属性与方法,开发者只需编写差异部分,大幅减少冗余代码抽象与具体——基类代表抽象概念(如"交通工具"),派生类代表具体实例(如"火车"),箭头从派生类指向基类is-a语义——火车是一种交通工具,但交通工具不一定是火车,这种关系具有方向性树状层级——多层次继承形成类层级结构,最上层最抽象,最下层最具体,支持从一般到特殊的逐级细化面向对象编程中类继承关系的教学示意INHERITANCECLASSIFICATION单一继承与多重继承的基本分类继承按基类数量分为单一继承(一个基类)和多重继承(多个基类)。单一继承关系简单、使用广泛;多重继承虽功能强大但复杂度高。继承体系允许多级层次但不允许循环依赖,这是保证类层级逻辑自洽的基本约束。单一继承派生类仅有一个基类,如"经理"和"销售员"各自继承自"职员",关系清晰易维护一个基类多重继承派生类同时拥有多个基类,如"销售经理"继承自"经理"和"销售员",可融合多方特性多个基类多级层次类A继承B、类C继承A可同时存在,形成"A→B→C"的链式派生结构A→B→C禁止循环继承不允许A继承B、B继承C、C又继承A的环路,否则编译器将报错无法通过编译器报错OBJECT-ORIENTEDDESIGN继承(is-a)与组合(has-a)的本质区别类与类之间有两种基本关系:继承关系表达"is-a"语义(派生类是基类的一种),组合关系表达"has-a"语义(一个类包含另一个类的对象)。正确区分这两种关系是合理设计类层次结构的前提。继承关系(is-a)派生类是基类的具体化:白马是马、轿车是汽车,派生类可以出现在基类能出现的任何场景中代码体现为class轿车:public汽车语法,轿车类自动拥有汽车类的全部接口和行为支持多态调用:基类指针可指向派生类对象,实现运行时的动态绑定和灵活扩展组合关系(has-a)一个类包含另一个类的对象作为成员:汽车包含轮胎、电脑包含CPU,是部分与整体的关系代码体现为类中将另一类的对象声明为成员变量,如class汽车{轮胎tires[4];};组合比继承耦合度更低,在不需要多态的场景下,"优先使用组合而非继承"是重要的设计原则CHAPTER02单一继承与访问控制深入派生类的定义语法、继承方式与成员访问权限控制规则C++INHERITANCE派生类的定义格式与语法要素C++派生类通过在类名后添加冒号、继承方式和基类名来定义。继承方式决定基类成员在派生类中的访问权限,默认为private。语法格式格式为class派生类名:继承方式基类名,继承方式常用public,默认为private继承。public·private构造与析构不可继承每个类必须定义自己的初始化与资源清理逻辑,构造函数和析构函数是类的特有行为,不参与继承。特有行为友元函数不可继承友元不是类的成员函数,只是被授予访问权限的外部函数,不参与继承体系。外部授权静态成员可继承且共享基类的static成员在派生类中可直接访问,基类与所有派生类共享同一份实例。staticInheritance&AccessControl三种继承方式对成员访问权限的影响C++提供public、private、protected三种继承方式,它们决定了基类成员在派生类中的新访问属性。公有继承保持原有权限不变(最常用),私有继承将可访问成员全部降为private,保护继承将public降为protected。private成员在任何继承方式下都不可被派生类直接访问。继承方式与成员访问权限对照表基类成员原始权限public继承后protected继承后private继承后publicpublicprotectedprivateprotectedprotectedprotectedprivateprivate不可访问不可访问不可访问基类private成员在任何继承方式下对派生类均不可直接访问,这是封装性的基本保障ASSIGNMENTCOMPATIBILITY赋值兼容规则:派生类向基类的隐式转换公有继承下派生类可隐式转换为基类,是多态的前提;此兼容严格单向,反向转换需显式操作且存在风险。01对象赋值与切片Baseb=derived;编译器自动执行切片(slicing),仅复制基类部分成员Slicing02指针赋值与多态Base*p=&derived;通过指针调用基类接口,配合虚函数实现运行时多态Polymorphism03引用初始化Base&r=derived;引用方式避免对象切片,是多态调用的推荐方式Reference04转换严格单向基类对象不能直接赋值给派生类,因派生类包含额外成员与状态One-WayChapter04·类的继承与派生对象切片(Slicing)问题与最佳实践当派生类对象按值赋给基类对象时,仅基类部分被复制,派生类新增成员被"切掉",称为对象切片。工程实践中应始终使用指针或引用进行向上转型,以保持对象完整性。切片陷阱示例赋值切片Students;Personp=s;此时p仅保留姓名和年龄,学号与专业信息被丢弃多态失效通过p调用虚函数时,动态绑定失效,始终调用Person版本参数传递voidfunc(Personp)按值传递时,传入Student对象派生部分同样丢失最佳实践使用指针Person*p=&s;指向完整Student对象,虚函数可正确动态绑定使用引用voidfunc(constPerson&p);不创建副本,保持对象完整性智能指针shared_ptr<Person>p=make_shared<Student>;兼顾安全与多态AccessControl使用using声明恢复基类成员访问权限当私有继承或保护继承导致基类public成员在派生类中降级时,可通过using声明选择性地恢复特定成员的访问权限。这是一种精细的访问控制手段,允许设计者在限制大部分接口的同时,有选择地暴露少数必要接口。using恢复机制私有继承将基类public成员降为private后,可用usingBase::func;在public区域重新声明以恢复访问。usingBase::func;访问可见性约束using声明仅对基类中可访问的成员有效:基类private成员因继承后不可见,无法通过using恢复。private不可恢复适用范围using声明可同时用于恢复函数成员和数据成员,且支持重载函数名的整体恢复而非逐个签名声明。重载整体恢复实践场景使用私有继承实现"基于实现而非接口的复用",再通过using精确暴露需要的接口。实现复用CHAPTER03多重继承与虚基类应对多基类继承的复杂性,理解菱形继承问题与虚基类解决方案CHAPTER04·INHERITANCE多重继承的语法定义与应用场景多重继承允许派生类同时拥有多个基类,语法上只需在冒号后以逗号分隔列出各基类及继承方式。它适合表达"兼具多种角色"的现实语义,如"助教既是教师又是学生",但也显著增加了类层次的设计复杂度和维护成本。语法格式class派生类:继承方式1基类1,继承方式2基类2{...};每个基类可独立指定public、protected或private继承方式,语法清晰直观classDerived:publicBase1,protectedBase2典型应用助教类同时继承教师类和学生类,融合教学能力和学习属性,完美表达"兼具多重身份"的现实语义,是多重继承最直观的应用场景助教类←教师类+学生类工程实践C++标准库iostream同时继承istream和ostream,实现双向输入输出能力,是工业级代码中多重继承的经典案例iostream:istream,ostream现代演进现代C++倾向于用接口类(纯虚基类)的多重继承替代传统多重继承,通过抽象接口降低耦合度,显著提高代码可维护性纯虚接口类多重继承Chapter4·Inheritance同名冲突(二义性)问题与消除策略多重继承中,当多个基类拥有同名成员时,派生类对该成员的访问将产生二义性,编译器无法确定应调用哪个基类的版本。冲突产生原因01Teacher和Student都定义了display()方法,TeachingAssistant调用时编译器报二义性错误,无法自动选择调用哪个基类版本02即使两个基类同名函数签名完全一致、功能相同,编译器也不会自动合并或选择,必须显式处理,这是C++多重继承的严格特性03同名数据成员同样冲突:若两个基类都有age成员,直接访问obj.age将编译失败,必须使用作用域限定符区分作用域限定符ta.Teacher::display()显式指定调用Teacher版本,适用于偶尔调用特定基类实现的场景,语法清晰直接派生类重写在TeachingAssistant中定义同名display(),内部按需调用两个基类版本,统一对外接口,是工程中最常用的解决方案using声明引入usingTeacher::display;可将指定基类版本优先引入派生类作用域,消除部分歧义,适用于单一基类版本优先的场景MultipleInheritance·DiamondProblem菱形继承问题:数据冗余与访问二义性菱形继承(钻石问题)发生在两个中间类共同继承同一基类、而最终派生类同时继承两个中间类的结构中。这导致最终派生类包含基类成员的两份副本,既浪费内存又产生访问二义性,是多重继承体系中最典型的结构性缺陷。结构特征A为公共基类,B和C各自继承A,D同时继承B和C,形成菱形拓扑结构菱形拓扑数据冗余D中包含两份A的成员副本(经B路径一份、经C路径一份),浪费内存且状态可能不一致两份副本访问二义性直接访问D中继承自A的成员时,编译器无法确定应通过B路径还是C路径访问,报编译错误编译错误现实类比助教继承教师和学生,教师和学生都继承自"人",但助教不应有两份姓名和两份身份证号身份证号INHERITANCE虚基类:virtual关键字解决菱形继承虚基类通过virtual关键字确保菱形继承中公共基类只存在唯一实例。使用虚基类后,最终派生类必须直接负责初始化虚基类。SYNTAX虚基类声明语法01在中间类继承基类时添加virtual关键字classB:virtualpublicA02virtual只需在直接继承公共基类的中间类中声明,最终派生类D正常继承B和C即可03编译器为含虚基类的对象插入vbptr指针,运行时通过指针间接定位唯一的基类子对象RULES构造与初始化规则01最终派生类D的构造函数必须直接调用虚基类A的构造函数,即使A不是D的直接基类02中间类B和C构造函数中对A的初始化调用会被忽略,由最终派生类统一负责,避免重复初始化03虚基类子对象的构造先于所有非虚基类,确保共享基类在任何派生逻辑执行前已完成初始化CHAPTER04·类的继承与派生虚函数表与动态绑定机制虚函数通过vtable/vptr机制实现运行时动态绑定:每个含虚函数的类维护一张虚函数指针表,对象内嵌vptr指向所属类的vtable。通过基类指针调用虚函数时,程序在运行时查表确定实际函数地址,实现"同一接口、不同行为"的多态效果。虚函数声明基类中用virtual关键字声明的函数,派生类可用override标识符显式标记重写版本virtual·overridevtable机制编译器为每个含虚函数的类生成vtable,表中存储该类所有虚函数的实际地址编译期生成vptr关联每个对象实例内含隐藏的vptr指针,构造时自动指向所属类的vtable,运行时据此查找函数运行期绑定虚析构函数必要基类析构函数必须声明为virtual,否则通过基类指针delete派生对象会导致派生部分内存泄漏防止内存泄漏CHAPTER04派生类的构造与析构理解派生类对象的生命周期管理,掌握构造与析构的调用顺序Chapter4·Inheritance派生类构造函数的初始化列表设计派生类构造函数必须通过初始化列表调用基类构造函数来初始化继承部分。若基类无默认构造函数,则必须在初始化列表中显式指定基类构造参数,否则编译失败。派生类新增成员也应在初始化列表中初始化,而非在函数体内赋值。01语法格式Derived(a,b):Base(a),memberB(b)Derived(a,b):Base(a),memberB(b)冒号后为初始化列表,先调基类构造函数再初始化新增成员变量02隐式调用Base()若初始化列表中未指定基类构造函数,编译器自动调用Base(),要求基类必须有默认构造函数03显式调用必需基类只有带参构造函数时,必须在初始化列表中传递参数,否则编译器报错无法通过编译04初始化优于赋值成员变量应在初始化列表中直接初始化,在函数体内赋值会先默认构造再赋值,效率更低Construction&DestructionOrder构造与析构的调用顺序规则C++严格规定构造顺序为"基类→对象成员→派生类构造函数体",析构顺序完全相反。这一"先进后出"的顺序保证了依赖关系的正确性——被依赖者先构造、后析构。构造顺序(从底到顶)01调用基类构造函数多重继承时按声明列表从左到右依次调用各基类构造函数02初始化对象成员按类中声明顺序依次调用各成员对象的构造函数03执行构造函数体基类和成员对象均已完成初始化,可安全使用析构顺序(从顶到底)01执行析构函数体先清理派生类自身分配的资源02逆序析构对象成员按声明逆序析构,后声明的成员先析构03逆序调用基类析构先声明的基类最后析构,确保依赖关系不被破坏C++Inheritance·DeepDive派生类拷贝构造与赋值运算符的设计派生类的拷贝构造函数必须在初始化列表中显式调用基类拷贝构造函数,赋值运算符必须在函数体内显式调用基类赋值运算符。遗漏这两步将导致基类部分使用默认构造或未被赋值,引发浅拷贝、double-free等严重内存错误。01拷贝构造函数初始化列表中必须传Base(o)而非Base(),确保基类部分通过拷贝构造正确初始化。Derived(constDerived&o):Base(o),member(o.member){}02遗漏基类拷贝的陷阱若写成Derived(constDerived&o):member(o.member),Base部分将用默认构造而非拷贝,导致基类数据未被正确复制。⚠Default-Init≠Copy-Init03赋值运算符函数体内需显式调用Base::operator=(other),再逐成员赋值,最后返回*this。Base::operator=(other);return*this;04RuleofThree/Five若类需要自定义析构函数,通常也需要自定义拷贝构造和赋值运算符;C++11后还需考虑移动构造与移动赋值语义。Destructor→Copy→Assign→MoveCHAPTER04·INHERITANCE运行时类型识别(RTTI)与安全向下转型C++的RTTI机制通过dynamic_cast和typeid提供运行时类型识别能力。dynamic_cast可安全地将基类指针向下转型为派生类指针,失败时返回nullptr而非产生未定义行为。使用前提是类体系中至少有一个虚函数,因为RTTI信息存储在虚函数表中。01dynamic_cast向下转型dynamic_cast<Derived*>(basePtr)运行时检查basePtr是否实际指向Derived对象,合法则返回有效指针02转换失败行为指针类型转换失败返回nullptr,引用类型转换失败抛出std::bad_cast异常03使用前提基类必须包含至少一个虚函数(通常声明虚析构函数即可),否则编译器报RTTI不可用错误04typeid操作符typeid(*ptr).name()可查询对象实际类型名称,常用于调试输出和条件分支的类型判断逻辑CLASSHIERARCHY综合案例:大学人员管理系统的类层次设计通过设计大学人员管理系统,将单一继承、多重继承、虚基类、构造/析构函数调用等知识点融会贯通。类层次结构BASECLASSPerson(基类):姓名、年龄、display()虚函数,虚析构函数确保多态delete安全VIRTUALINHERITTeacher/Student:分别虚继承Person,新增工号/职称与学号/专业MULTIINHERITTeachingAssistant:多重继承Teacher和Student,Person数据仅存一份关键实现要点CONSTRUCTORTA构造函数必须直接调用Person构造函数,Teacher和Student中对Person的初始化调用将被忽略CONFLICTRESOLVETA中调用display()需明确指定Teacher::display()或Student::display()以消除同名冲突DESTRUCTORPerson析构函数声明为virtual,确保deletepersonPtr时能正确调用完整析构链ABSTRACTBASECLASS纯虚函数与抽象基类的接口设计纯虚函数(=0)强制派生类必须实现指定接口,含有纯虚函数的类称为抽象基类,不可实例化。这种机制为继承体系提供了接口契约——保证所有具体派生类都实现了约定的方法,是多态设计和框架开发的基础。声明语法纯虚函数无实现体,标记为"=0"后编译器强制派生类提供实现,确保接口语法统一。这是C++实现接口规范的核心机制。SYNTAX=0抽象基类约束含纯虚函数的类不能创建对象实例,只能作为接口规范被继承,起"蓝图"和"契约"作用。抽象基类定义了派生类必须遵守的接口标准。CONSTRAINTInterface派生类实现若派生类未重写全部纯虚函数,该派生类也变为抽象类,同样不可实例化。只有完全实现所有纯虚函数的类才能创建具体对象。IMPLEMENTATIONOverride概念互补C++20Concepts约束模板参数,抽象基类约束继承体系,两者配合更安全。Concepts在编译期检查,抽象基类在运行期支持多态,形成完整约束体系。COMPLEMENTConceptsC++11InheritanceSafetyoverride与final:C++11的继承安全机制override关键字强制编译器验证派生类函数是否正确重写了基类虚函数,签名不匹配时立即报错。final关键字禁止类被进一步继承或虚函数被进一步重写。两者配合使用可在编译期捕获大量继承相关的隐蔽错误。CodeExample//BaseclassclassBase{virtualvoid
display()const;virtualvoid
process(int);};//override:catchessignatureerrorsclassDerived:publicBase{void
display()constoverride;//✓//voiddisplay()override;←ERROR};//final:preventsfurtheroverride/inheritanceclassLeaffinal:publicDerived{void
process(int)overridefinal;};override+final配合使用,编译期消除继承隐患override编译验证:voiddisplay()override;编译器验证基类是否存在同名同签名的虚函数,不存在则报编译错误常见捕获错误:参数类型不匹配、遗漏const修饰符、基类函数忘记声明virtual等,均可被override在编译期发现最佳实践:所有意图重写基类虚函数的派生类方法都应添加override,零成本显著提升代码安全性类级final:classLeaffinal阻止该类被任何其他类继承,适用于不希望被扩展的终端类函数级final:voidfunc()final;阻止派生类进一步重写此虚函数,编译器可对final虚函数做去虚拟化优化设计意图:final表达"此类/函数已完成最终设计"的语义,防止继承体系无序膨胀和行为不可预测CHAPTER04·INHERITANCE继承体系中静态成员的特性与设计基类的静态成员在整个继承体系中只有一份实例,被所有派生类共享。派生类可通过自身类名访问共享的静态成员,但不能通过声明同名静态成员来'覆盖'基类版本——这只会造成名称隐藏。共享特性Base中声明的staticintcount只有一份实例,Derived::count和Base::count指向同一内存地址SHAREDINSTANCE名称隐藏若Derived中重新声明staticintcount,则隐藏Base::count,两者变为独立变量NAMEHIDING访问方式可通过类名、对象或指针访问,推荐类名方式Base::count更清晰直观SCOPEACCESS函数限制无this指针,不能访问非静态成员,不能声明为virtual,不参与多态NOTHISPTRC++·INHERITANCE&FRIENDSHIP友元关系与继承的交互规则友元关系不具有继承性——基类的友元不能自动成为派生类的友元,也不具有传递性。设计时应尽量限制友元使用范围,避免破坏封装完整性。友元不可继承F是Base的友元,F可访问Base的private成员,但无法访问Derived新增的private成员。友元权限仅限于声明它的类,不会随继承链向下传递。NoInheritance友元不可传递A是B的友元、B是C的友元,不意味着A是C的友元。友元关系是单向的、非传递的,每次访问权限都需要独立显式授权。NoTransitivity可访问基类私有部分通过基类对象的引用或指针,友元函数可操作基类的私有数据成员。这是友元机制的核心能力,但仅限于基类作用域内的成员。BasePrivateOK设计建议优先使用protected成员替代友元来给派生类授权,友元仅在运算符重载等特殊场景使用。过度使用友元会破坏封装边界,增加维护成本。protected>friendChapter4·Summary本章知识体系总览与能力要求本章围绕"类的继承与派生"构建了从概念到实践的完整知识体系,涵盖继承语义、权限规则、多层继承结构、构造与拷贝语义及多重继承与多态问题。概念层(理解)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 骨质疏松症规范化诊断与骨密度T值精准解读
- 中西医结合传染病学试卷A
- 2026年福建厦门高新人才开发有限公司会计岗招聘1人笔试备考试题及答案详解
- 2026年绥化安达市公安局公开招聘警务辅助人员10人笔试备考题库及答案详解
- 甘肃省市县重点高中教研协作联盟2026-2027学年高三起点摸底考试数学试卷(含答案)
- 2026年尚义县网格员招聘考试备考试题及答案解析
- 2026福建莆田城厢区顶墩实验学校中小学编外教师自主招聘笔试备考试题及答案详解
- 重庆飞驶特人力资源管理有限公司派往某市级部门直属事业单位招聘认证技术管理1人笔试备考题库及答案详解
- 2026宁波市鄞州第二实验中学非编代课教师招聘1人考试备考题库及答案详解
- 2026国药控股股份有限公司招聘笔试参考题库及答案详解
- 理解与表达(第三版)课件 第一单元
- 河埠头施工方案(3篇)
- 胃溃疡合并胃出血个案护理
- 开学第一课课件2025-2026学年湘教版八年级地理下册
- 生产车间节约用电制度
- 天津天津东疆综合保税区管理委员会面向社会招聘笔试历年参考题库附带答案详解
- 街道商会档案管理制度
- 监控设备调试施工方案
- 5年高考数学真题分类汇编专题03等式与不等式、基本不等式及一元二次不等式(原卷版)
- 2026年山东能源集团西北矿业有限公司招聘(200人)笔试参考题库附带答案详解(3卷)
- 中小企业财务管理制度与流程
评论
0/150
提交评论