华为 - C中级培训教材

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

内部资料,注意保密C++中级培训教程员工培训中心编辑2005年6月V1.0华为技术有限公司华为技术前言C++语言中级教材讲授C++语言的运用技术,包括:类、对象之间的关系、对象的存储与布局、运算符重载、智能指针、仿函数、泛型编程,C++模式设计基本思想。NE002009cV1.01业务与软件C++语言项目C++进阶目录第一章类、接口…………………………………………………………………71.1Handle-Body与接口、抽象接口…………………………………………71.2多继承、与菱形缺陷、this跳转等………………………………………131.3C++多态的两种多态形式和区别……………………………………………18第二章重载………………………………………………………………………182.1函数重载………………………………………………………………………192.2运算符重载…………………………………………………………………20第三章模板………………………………………………………………………293.1模块函数……………………………………………………………………293.2模块类……………………………………………………………………………313.3STL标准模板库…………………………………………………………………34附录:参考资料………………………………………………………………………39ISC基本知识附录:名词解释5前言我们在C++基础课程中已经了解了C++的一些基本概念,知道了什么是类什么是对象。也了解了继承、封装、多态等C++面向对象的基本特征,本课程主要是更进一步探讨一下C++一些基本模型的应用,加深对概念的理解,由于课程时间有限,C++,模型和内容又如此之多,对任何一个模型都无法深入进去,所以只能泛泛而谈。第一章类、接口学习要求:1、了解类的继承、封装等概念之间的关系2、了解什么是接口,什么是虚函数,它有什么样的特点。学会使用接口编程的思想本章节主要介绍C++中的类、接口。类,包涵了一组数据和一组基于数据上的一组方法。它描述了一个对象的属性、状态和行为;接口,它只是描述了一个对象的简单的行为。有关类的基本概念:ClassnamesClassmembersMemberFunctionsStaticMemberFunctionsUnionsC++BitFieldsNestedClassDeclarationsTypeNamesinClassScopeMultipleBaseClassesVirtualFunctionsAbstractClassesControllingAccesstoClassMembersprivateMembersprotectedMemberspublicMembersISC基本知识附录:名词解释6AccessSpecifiersforBaseClasses,priavte,public、protectedFriendsConstructorsDestructorsConversionFunctionsthenewoperatorandthedeleteoperatorCopyingConstructorFunctionsInterface1.1Handle-Body与接口、抽象接口在C++中封装的概念是把一个对象的外观接口同实际工作方式(实现)分离开来,但是C++的封装是不完全的,编译器必须知道一个对象的所有部分的声明,以便创建和管理它。我们可以想象一种只需声明一个对象的公共接口部分的编程语言,而将私有的实现部分隐藏起来。C++在编译期间要尽可能多地做静态类型检查。这意味着尽早捕获错误,也意味着程序具有更高的效率。然而这对私有的实现部分来说带来两个影响:一是即使程序员不能轻易地访问实现部分,但他可以看到它;二是造成一些不必要的重复编译。然而C++并没有将这个原则应用到二进制层次上,这是因为C++的类既是描述了一个接口同时也描述了实现的过程,示例如下:classCMyString{private:constintm_cch;char*m_psz;public:CMyString(constchar*psz);~CMyString();intLength()const;intIndex(constchar*psz)const;}ISC基本知识附录:名词解释7CMyStirng对外过多的暴露了内存布局实现的细节,这些信息过度的依赖于这些成员变量的大小和顺序,从而导致了客户过度依赖于可执行代码之间的二进制耦合关系,这样的接口不利于跨语言跨平台的软件开发和移植。1.1.1Handle-Body模式解决这个问题的技术有时叫句柄类(handleclasses)或叫“CheshireCat”[1]。有关实现的任何东西都消失了,只剩一个单一的指针“m_pThis”。该指针指向一个结构,该结构的定义与其所有的成员函数的定义一样出现在实现文件中。这样,只要接口部分不改变,头文件就不需变动。而实现部分可以按需要任意更动,完成后只要对实现文件进行重新编译,然后再连接到项目中。这里有这项技术的简单例子。头文件中只包含公共的接口和一个简单的没有完全指定的类指针。classCMyStringHandle{private:classCMyString;CMyString*m_pThis;public:CMyStringHandle(constchar*psz);~CMyStringHandle();intLength()const;intIndex(constchar*psz)const;};CMyStringHandle::CMyStringHandle(constchar*psz):m_pThis(newCMyString(psz));{}CMyStringHandle::~CMyStringHandle(){deletem_pThis;ISC基本知识附录:名词解释8}intCMyStringHandle::Length(){returnm_pThis-Length();}intCMyStringHandle::Index(constchar*psz){returnm_pThis-Index(psz);}这是所有客户程序员都能看到的。这行classCMyString;是一个没有完全指定的类型说明或类声明(一个类的定义包含类的主体)。它告诉编译器,cheshire是一个结构的名字,但没有提供有关该结构的任何东西。这对产生一个指向结构的指针来说已经足够了。但我们在提供一个结构的主体部分之前不能创建一个对象。在这种技术里,包含具体实现的结构主体被隐藏在实现文件中。在设计模式中,这就叫做Handle-Body模式,Handle-Body只含有一个实体指针,服务的数据成员永远被封闭在服务系统中。Handle-Body模式如下:图1Handle-Body模式(句柄类做为接口)Handle-Body的布局结构永远不会随着实现类数据成员的加入或者删除或者修改而导致Handle-Body的修改,即Handle-Body协议不依赖于C++实现类的任何细节。这就有效的classHandlem_pThisclassISC基本知识附录:名词解释9对用户的编译器隐藏了这些斜街,用户在使用对这项技术时候,Handle-Body接口成了它唯一的入口。然而Handle-Body模式也有自己的弱点:1、接口类必须把每一个方法调用显示的传递给实现类,这在一个只有一个构造和一个析构的类来说显然不构成负担,但是如果一个庞大的类库,它有上百上千个方法时候,光是编写这些方法传递就有可能非常冗长,这也增加了出错的可能性。2、对于关注于性能的应用每一个方法都得有两层的函数调用,嵌套的开销也不理想3、由于句柄的存在依然存在编译连接器兼容性问题。接口和实现分离的Handle-Body。1.1.2抽象接口使用了“接口与实现的分离”技术的Handle-Body解决了编译器/链接器的大部分问题,而C++面向对象编程中的抽象接口同样是运用了“接口与实现分离”的思想,而采用抽象接口对于解决这类问题是一个极其完美的解决方案。1、抽象接口的语言描述:classIMyString{virtualintLength()const=0;//这表示是一个纯虚函数,具有纯虚函数的接口virtualintIndex(constchar*psz)const=0;};2、抽象接口的内存结构:ISC基本知识附录:名词解释10图2抽象接口的内存布局3、抽象接口的实现代码:接口:classIMyString{virtualintLength()const=0;//这表示是一个纯虚函数,具有纯虚//函数的接口virtualintIndex(constchar*psz)const=0;};实现:classCMyString:publicIMyString{private:constintm_cch;char*m_psz;public:CMyString(constchar*psz);virtual~CMyString();intLength()const;intIndex(constchar*psz)const;classvtprclass::m1class::m2ISC基本知识附录:名词解释11}从上面采用抽象接口的实例来看,抽象接口解决了Handle-Body所遗留下来的全部缺陷。抽象接口的一个典型应用:抽象工厂(AbstractFactroy)图3抽象工厂模式1.2多继承与菱形缺陷、this跳转等多重继承是C++语言独有的继承方式,其它几乎所有语言都秉承了单一继承的思想。这是因为多重继承致命的缺陷导致的:1.2.1菱形缺陷当继承基类时,在派生类中就获得了基类所有的数据成员副本。假如类B从A1和A2两个类多重继承而来,这样B类就包含A1、A2类的数据成员副本。考虑如果A1、A2都从某基类派生,该基类称为Base,现在继承关系如下:ISC基本知识附录:名词解释12A1A2BaseB图4菱形继承关系我们C++语言来描述这种继承关系:classBase{……};classA1:publicBase{……};classA2:publicBase{……};classB:publicA1,publicA2{……};那么A1、A2都具有Base的副本。这样B就包含了Base的两个副本,副本发生了重叠,不但增加了存储空间,同时也引入了二义性。这就是菱形缺陷,菱形缺陷时间是两个缺陷:1、子对象重叠2、向上映射的二义性。菱形缺陷的其中一种解决办法将在C++世界里最广泛的使用虚拟继承解决菱形缺陷的应用便是标准C++的输入/输出iostream;ISC基本知识附录:名词解释13basic_ostreambasic_iostreambasic_iosiostreamvirtualvirtual图5标准C++的输入/输出1.2.2多重接口与方法名冲突问题(Siamesetwins)对继承而来的虚函数改写很容易,但是如果是在改写一个“在两个基类都有相同原型”的虚函数情况就不那么容易了。提出问题:假设汽车最大速度的接口为ICar,潜艇最大速度的接口为IBoat,有一个两栖类的交通工具它可以奔跑在马路上,也可以航行在大海中,那么它就同时拥有ICar、IBoat两种交通工具的最大速度特性,我们定义它的接口为ICarBoat;classICar{virtualintGetMaxSpeed()=0;};classIBoat{virtualintGetMaxSpeed()=0;};我们先对ICarBoat的接口做一个尝试:classCCarBoat{virtualintGetMaxSpeed();//既完成ICar的GetMaxSpeed()接口方法又//完成IBoat的接口方法?显然不能够};ISC基本知识附录:名词解释14解决问题:显然上面这个尝试根本就无法成功,只用一个实现方法,怎么能够求出这个ICarBoat交通工具奔跑在马路上的最高时速,同时也能够

1 / 37
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功