C++程序设计基础教程

上传人:仙*** 文档编号:243543129 上传时间:2024-09-25 格式:PPT 页数:346 大小:2.26MB
返回 下载 相关 举报
C++程序设计基础教程_第1页
第1页 / 共346页
C++程序设计基础教程_第2页
第2页 / 共346页
C++程序设计基础教程_第3页
第3页 / 共346页
点击查看更多>>
资源描述
,第二期更新内容,C+11/14,标准,Lambda,、,static_assert,,,type traits,,,Move semantics,。,WIN32,消息,绘图,控件,资源,文件,内存,进程,线程。,起源,语言特点,语言缺点,C+,语言及相关软件介绍,day01,前景与方向,编译器安装与配置,由,C+,起源:,1974,年,Bjarne,博士在分析与研究,UNIX,系统由与内核分布面造成的网络流量时试图寻找一种有效工具使其更加模块化 他在,c,的增加了类似,Simula,的类的机制 并与,1983,年开发一种新的语言,C+;,C+,的语言特点,1,兼容,c,且继承了,c,的特性,并同,c,一样高效且可移植,2,属于面向对象的编程,抽象 封装 继承 多态,3,语言灵活 (类的层次结构设计)且支持指针,3,支持运算符重载,4,异常处理机制,5,支持泛型编程,T f(T x) return x*x ;,6,多种类库的支持,语言缺点:,语言复杂,支持多种设计风格,复杂的,c+,程序正确性不易保证,C+,的发展方向,windows,平台,unix,平台,嵌入式,C+,也是一种编译型的语言,推荐使用,vs2013,编译环境 其他可选,vc6.0 vs2010 nodepad+,vs 2013,基本支持,c11,标准,vs2010,以上,Vs 2013,是微软公司的一款软件开发平台,IDE(,集成开发环境,),Vs2013,的安装使用,1,安装前需要先安装,IE10,提供支持,2,下载安装包, 选择安装位置 如下:,4,安装,vs 2013,5,安装完成(,20,分钟左右),如何建立一个,c+,程序,文件,-,新建,-,(,visual c+,类型),+win32 console application,自定义 文件名 文件路径,-,应用程序设置,-,其他选项,-,空工程,-,源文件,-,新建条目,-c+,文件,-,添加,-,完成,C+,的头文件,名字空间,简单的,i/0,函数,一个简单的,c+,程序,day02,C+,风格的操作,Vs2013,基本设置,行号设置:,工具,-,选项,-,文本编辑器,-,所有语言,-,行号 选中,快捷键:,1,复制:如果你想复制一整行代码,只需将光标移至该行,再使用组合键,“,Ctrl+C”,来完成复制操作,而无需选择整行,2,剪切:如果你想剪切一整行代码,只需将光标移至该行,再使用组合键,“,Ctrl+X”,来完成剪切操作,而无需选择整行。,3,删除:如果你想删除一整行代码,只需将光标移至该行,再使用组合键,“,Ctrl+L”,来完成剪切操作,而无需选择整行。,4,粘贴:如果你想粘贴你已经复制的内容 将光标移至该行 再使用组合键,“,Ctrl+v,”,来完成粘贴操作,5,撤销:使用组合键,“,Ctrl+Z”,进行撤销操作;,6,反撤销:使用组合键,“,Ctrl+Y”,进行反撤销操作。,7,查找:,Ctrl+f,(,Ctrl+H,替换),8,移动光标 :,home,行首,end,行尾,调试相关,1,)调试(启动):,F5,;,(,调试器,),2,),ctrl + s,保存修改,4,)调试(逐语句):,F11,;,5,)调试(逐过程):,F10,;,6,)设置断点:,F9,。,7),调试不执行,:F7,1,创建源文件,c+,的源文件的扩展名使用:,.cpp .cc .C .cxx,2 #include,为,c+,标准库的,i/o,函数的头文件,c+,旧式风格:,iostream.h,c+,新式风格:,iostream cstring,3 using namespace std;,using,编译指令 指定使用的名字空间,namespace std,标准名字空间,4 cin a;,cout aendl;,c+,的 输入输出的方式,cout,为一个对象,c+,没有格式化字符串输出 但有相应的格式化的控制符和流函数,cout/cin,还有明显的优点 :,类型识别功能 可扩展性(重定义,运算符支持各种数据类型),endl;,控制符 移动到光标所在的下一行,二,c,风格的操作,1 #include,导入,c,头文件,#include,#include”add.h” /h,可以不加,其他库函数 包含对应的头文件 正常使用,例:,strcpy(a,b);,编译:,终端窗口:,gcc ap1.cpp lstdc+,g+ ap1.cpp,vs,开发环境:,F 7,相同,名字空间的引入,定义,使用,名字空间,day03,嵌套,无名名字空间,名字空间的引入:,在,C+,中名称可以是变量 函数 结构体 类 及类的相关成员 使用第三方类库,时 极有可能出现名称冲突,c+,利用作用域的特性引入了名字空间的概念,名字空间:名字空间是一种描述,逻辑分组,的机制,send(sendEx) sendsendEx,防止,命名冲突 跨文件访问,注意:,名字空间 可以是全局的 可以是位于另一个名称空间中 不可以存在于代码块中,1,定义:,namespace A,int I;,double d;,void show();,namespace B,int I,float f;,A,中的,I,与,B,中的,I,并不发生冲突,2,相同名字空间可以多次添加补充名字空间的内容,namespace A,show(),.,;,非用户定义的名称空间存在于 全局命名空间,int I;,使用,: A:I = 0;,B:I = 1;,:I = 2; /,全局命名空间,: 为作用域解析运算符 (域运算符),1 Using :,为了避免每次都使用名字空间时都要其进行名字空间限定,可以使用,using,对名字空间内的内容进行特定区域的声明,using A:I; /using,声明,std:cout,再次使用可以直接调用名称而无需增加空间限定,这种声明可以全局全局域同名变量,std:cout int I namespace Aint imain,2 using :,作为编译指令的使用 使对应名字空间内的所有内容可用 且使用时可,以省略作用域解析运算符,using namespace A ;,注意事项:,1,避免歧义,using A:I;,using B: I;,I=1; /?,哪一个?,2,不要用,using,声明相同名称的内容,using A:I ;int I;,3 using,做编译指令时 名称空间为全局 如果局部于名称空间的,名字相同 则局部覆盖名字空间内容,namespace extern int i,4,局部名称会覆盖全局与,using,指令的名字空间内容 但可以用,I,(局部),:I,(全局),A,:,I(,名字空间,),区分使用,5 using,声明比,using,编译安全,声明是指定具体内容 编译器发出指示,编译指令导入全部名字空间内容 可能发生冲突 覆盖时编译器,不会发出警告,名字空间的嵌套,Namespace A,int a;,namespace B,int b;,访问:,A,:,B,:,b =1;,未命名名字空间,:,内部链接特性 与,static,修饰的内容特性相同,Namespace ,int a;, coutaendl;,补充:,1 Iostream,相关函数 存放在,std,的名字空间内,Using,Std:cout.,内联名字空间(,c+11,),关键字,inline,一种新的嵌套名字空间的使用方式,嵌套在名字空间的内联名字空间在使用时不需其名字空间进行限定使用,Inline namespace inspace ,布尔类型,string,类型,结构体,数据类型,day04,联合,枚举,1,新的数据类型:,布尔类型:,bool,表示布尔量的数据类型,取值: 由字面值常量,true (,非零,),真,false (0 NULL false 0),构成,true,bool isok =true;,bool notok = false;,2,字面值,true false,可以通过提升转换为,int,类型,true 1 false 0,int a = true; / a = 1;,3,任何基本类型都可以被隐式转换为布尔类型,转换后 非,0,为真,0,为假,二,String,类型(类),(,自动处理大小,),使用需要添加头文件,string,C,语言中是用字符数组来存放字符串,char a110=“abc”,a22=a,0;,1,初始化,:string str1; string str2 = “abc”;,2 String,可以做 赋值,拼接 等功能,结构体:,在,c+,中结构体内允许定义函数 且结构体在计算大小时为,1,而,C,中为,0,在定义结构体时可以省略关键字,struct,联合:定义时可以省略联合名为 匿名联合,(),访问时可以不用加联合的前缀,X.,枚举:枚举类型在,c+,中为一个独立的类型 不能把一个整数赋值给一个枚举变量,C+11:,1,类型的占位符,auto,根据初始化的内容推断变量类型,作用简化代码,2 nullptr,std:nullptr_t,类型的值,用来指代空指针,nullptr,和任何指针类型以及类成员指针类型的空值之间可以发生,隐式类型转换,同样也可以隐式转换为,bool,型,.,强类型枚举,C+11,中通过引入了一个称为强类型枚举的新类型,修正了这种情况。强类型枚举由关键字,enum class,标识。它不会将枚举常量暴露到外层作用域中,也不会隐式转换为整形,并且拥有用户指定的特定类型(传统枚举也增加了这个性质),函数重载,(,函数多态,),重载机制,哑元函数,函数重载一,day05,1,概念:同一作用域的一组参数列表不同,函数名相同的函数 这组函数叫,函数重载(,C+,允许定义相同名称的函数),作用:,重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,,避免了名字空间的污染,对于程序的可读性有很大的好处(一物多用),参数列表不同:,1,参数类型不同,2,参数顺序不同,3,参数个数不同,重载版本根据参数的匹配度进行选择,注意:,1.1,与函数参数的变量名无关,1.2,函数的返回值类型与重载无关,2,函数重载的实现原理是通过,c+,换名实现的,extern “C” int fun(),的形式可以以,c,的方式生成函数名(无换名机制),3,使用场景:,当函数基本上执行相同的任务 使用不同形式的数据时,哑元函数,缺省参数,内联函数,函数重载二,day06,哑元函数:参数只有类型没有形参名的函数,void fun(int);,功能:,1,保持向前兼容性,2,做函数的区分,T operator+() ,T operator+(int),缺省参数,如果函数的形参有缺省值,当函数调用时没有传递实参,那么形参就使用缺省,值,如果调用函数时传递了实参,那么形参就使用实参的值,注意:,1,缺省参数靠右原则 如果一个函数有多个参数 且部分参数有缺省值那么缺,省值的参数必须靠右,(,在编译期间确定参数,),2,如果函数的声明和定义分开 那么缺省参数只能写在函数的声明部分,3,注意防止重载的冲突(歧义),4 c+,中函数的规则 不接受任何参数(否则可能构成重载),5,凼数参数的缺省值叧能在凼数声明丨指定,3,内联 :函数使用关键字,inline,关键字修饰的函数叫做内联函数,函数调用过程 :调用用后立即存储该指令的内存地址,将函数参数复制到堆栈,跳到标记函数起点的内存单元 执行函数代码(可能还有返回,值放入到寄存器中),将返回值弹出,然后跳回到地址被保存的指令处,内联的实质:,就是把函数编译好的二进制代码 替换成函数的调用指令(省去了调用开销),(空间换取时间),注意:,1,类中直接定义的函数自动被处理成内联函数,所以一般把内联函数放在头文,件中,2 inline,是一种请求,实现方式取决于编译器,特别是当函数较大或是递归,的时候,1,引用的概念,2,如何创建一个引用,3,引用的本质,指针与引用,day07,4,引用的应用,5,引用与指针,1,引用:引用是已定义变量的别名 ,为,c+,新增的一种复合类型,2,创建一个引用:,int var_i;,int &,revar_i = var_i;,注意:,1,这里的,&,不是取址符而是类型标识符的一部分,2,创建引用时必需初始化,3,引用的内容不能为空,null,4,引用创建之后就不能更换引用的内容,int ,这样定义之后我们就可以用,var_i,或,rvar_i,来操作变量,var_i ;,3,引用的本质:引用的内部是由指针完成实现的,int* double*,其本身并非一个实体类型(可由,sizeof,证明),int& double &,4,引用的应用:,4.1,做函数的参数 省去函数参数进行复制时的内存开销,常引用型的参数 可以防止实参被无意修改 且可以接受常量型与,非常量型参数,foo(const int&i)I = 0 foo(a),4.2,做函数的返回值 做返回值时需保证返回值的有效性,注意:不能返回局部变量的引用,也可以返回常引用型的返回值,补充:左值 与非左值,(,右值,),一般的左值参数是可以被引用的数据对象 如:变量 数组元素 结构成员,引用 和解除引用的指针都是左值,非左值包括 字面常量(引号括起的字符串除外,它们由其地址表示),和包含多项的表达式,int I;I =10; 10 =I; string s1 = s2+s3+s4;,(a+),临时变量,temp (a+1),右值,int c = (a+b),右值,;,“,abc,”,= “abc”,(+a) = 1;,左值,int,右值引用,5,指针与引用,5.1,指针是一个实体存放地址 而引用仅是一个内存的别名,5.2,引用必须初始化 且初始化后不可更换其引用的目标,指针可以不初始化 且其指针的指向的内容可随时更换(常指针除外),5.3,引用不可以为空 指针可以为空/ char*pc = 0;char.,5.4,引用的大小为所引用变量的大小 指针为,4,个字节,5.5,因引用是一个内存的别名 所以不存在引用引用的引用和引用数组,但存在指向指针的指针和指针数组,5.6 在使用时,如果你的变量的指向可能发生变化或为空,请使用指针,,如果你的变量不允许为空,可以引用,5.7 不存在空引用的事实意味着引用的代码比指针的代码效率要高,(无需检查其他合法性),5.8 重载某些运算符时,必须用到引用做返回值,C,语言的类型转换,C+,的类型转换,Static_cast,类型转换,day08,Const_cast,Reinterpret_cast,C+,提供丰富的不同的数据类型 当不同类型在进行算术运算 参数传递等一系列的操作时因计算机的特性不得不将不同的类型进行转换后再进行操作,1,初始化和赋值进行的转换(,int)d int(d),=,右边的类型将会转换成左边的数值类型 (赋值后的数值不安全),2,以,方式初始化时进行的转换(不允许缩窄 浮点转换整型)(,c+11,),3,表达式中的转换,类型提升,4,传递参数时的转换,5,强制类型转换,5.1,(,typename,),value :,标,c,typename(value),:,c+,5.2 static_cast (,源类型变量,)a - b,隐式类型转换的逆转换,转换时做静态检查 (在编译时进行),检查(诸如指针越界计算,类型检查),Char -int,Int char,5.3 const_cast (,源类型变量,),去除指针或引用上的,const,属性,void foo(const int *i),5.4 reinterpret_cast (,源类型变量,),任意类型的指针或引用或整型之间的转换 但不可改变,const,属性,其他限制是不能转换成比指针更小的类型 不能将函数指针与其他,类型进行转换,5.5 dynamic_cast (,源类型变量,),多态父子类指针或引用之间的转换 动态转换,New,的使用方法,Delete,使用方法,Lambda,表达式,动态内存分配,/lambda,表达式,day09,C+,在添加动态分配运算符,new delete,的同时,支持标准,C,的动态分配库函数,语法:,1 type_name *pointer_name = new type_name; /,未初始化,说明:与,malloc,不同,new,会根据类型的不同自动分配对应的内存大小,且返回对应类型的指针,2 type_name *pointer_name = new type_name(value)/,初始化,3 type_name *pointer_name = new type_name()/,初始化为零,4 type_name *pointer_name = new type_namen,分配,n,个,type_name,的数据的内存大小,4 type_name *pointer_name = new type_namen=1,,,2,,,3,,,4.,c+0x,标准 初始化数组时进行初始化,5 delete pointer_name,与非,new,配对使用,6 delete pointer_name,与,new,配对使用,某些编译器在分配数组的大小时会在所分配的内存前多加,4,个字节大小,用于存放分配的数组大小,7,对,new,分配内存是否失败的判断,new,操作符会抛出,bad_alloc,异常,C+,之父给,C,程序员的建议,1.1,尽量的少使用宏使用,inline,函数 替代带参的宏使用,const enum,去替代常量宏,1.2,使用,namespace,去避免命名冲突,1.3,变量随时用随时定义以保证初始化,1.4,尽量少使用强制类型转换 如果必须转换就使用四个转换运算符中的一个,1.5,少使用,malloc free,因为,new delete,会做的更好,1.6,尽量少使用,C,风格的字符串 因为,string,会使用更方便,1.7,逐步建立 面向对象的思想,Lambda,表达式”,(lambda expression),是一个,匿名函数,,即没有函数名的函数。,Capture,子句,Lambda,可在其主体中引入新的变量(用,C+14,),它还可以访问(或“捕获”)周边范围内的变量。,1.var,表示值传递方式捕捉变量,var,;,2.=,表示值传递方式捕捉所有父作用域的变量(包括,this,);,3.&var,表示引用传递捕捉变量,var,;,4.&,表示引用传递方式捕捉所有父作用域的变量(包括,this,);,5.this,表示值传递方式捕捉当前的,this,指针。,空,capture,子句, ,指示,lambda,表达式的主体不访问封闭范围中的变量。,可以使用默认捕获模式(标准语法中的,capture-default,)来指示如何捕获,lambda,中引用的任何外部变量(使用,capture-default,时,只有,lambda,中提及的变量才会被捕获),注意事项:,引用捕获可用于修改外部变量,而值捕获却不能实现此操作。 (,mutable,允许修改副本,而不能修改原始项。),引用捕获会反映外部变量的更新,而值捕获却不会反映。,引用捕获引入生存期依赖项,而值捕获却没有生存期依赖项。 当,lambda,以异步方式运行时,这一点尤其重要。 如果在异步,lambda,中通过引用捕获本地变量,该本地变量将很可能在,lambda,运行时消失,从而导致运行时访问冲突。,参数列表,在,C+14,中,如果参数类型是泛型,则可以使用,auto,关键字作为类型说明符。 这将告知编译器将函数调用运算符创建为模板。 参数列表中的每个,auto,实例等效于一个不同的类型参数。,可变规范,通常,,lambda,的函数调用运算符为,const-by-value,,但对,mutable,关键字的使用可将其取消。 它不会生成可变的数据成员。 利用可变规范,,lambda,表达式的主体可以修改通过值捕获的变量,返回类型,将自动推导,lambda,表达式的返回类型。 无需使用,auto,关键字,除非指定尾随返回类型。,trailing-return-type,类似于普通方法或函数的返回类型部分。 但是,返回类型必须跟在参数列表的后面,你必须在返回类型前面包含,trailing-return-type,关键字,-,。,如果,lambda,体仅包含一个返回语句或其表达式不返回值,则可以省略,lambda,表达式的返回类型部分。 如果,lambda,体包含单个返回语句,编译器将从返回表达式的类型推导返回类型。 否则,编译器会将返回类型推导为,void,Lambda,体,从封闭范围捕获变量,如前所述。,参数,本地声明变量,类数据成员(在类内部声明并且捕获,this,时),具有静态存储持续时间的任何变量(例如,全局变量),面向对象,抽象,类与对象,类与对象,day10,C+,是一种面向对象的编程语言,面向对象(,oop,)是一种特殊的 设计程序的概念性方法,C+,的一些语言特性使得应用这种方法更容易,OPP,特性: 抽象 封装 继承 多态 代码重用,1,抽象:,现实空间 逻辑抽象 计算机,学生 学生类,STUDENT,学生:,属性:,string name;,string major;,double score;,行为:,void study();,void exam();,void play();,2,类: 具有相同的属性和行为的对象被分成一组 即为一个类,类在,c+,中为一种自定义复合类型 :成员变量 成员函数,(,方法,),3,对象: 类是对现实世界的抽象 对象则是类在程序中的一个虚拟的实例,可以用类来声明变量,(,也称为实例,),。每个实例是类的一个对象,4,使用类来描述一个类,struct/class STUDENT,访问控制限定符:,/struct,无,string name;,int stuID;,double score;,void study();,void exam();,void play();,5,实例化:定义类的实例可以称为类的实例化,STUDENT student ;,6 struct,定义类 成员默认为公开,class,定义类 成员默认为私有,7,成员控制限定符,public:,公有成员 任意访问,protected :,保护成员 只有本类成员和子类可以访问,private:,私有成员 只有本类成员可以访问,对不同成员的访问控制属性加以区分 体现了,c+,作为面向对象程序设计语言的,封装特性,8,类的声明与实现可以分开(分开后则不能形成内联),如何初始化对象,创建过程,对象的创建过程,day11,如何初始化成员对象?(因为私有成员的存在),C+,为类的初始化提供了一个特有的函数,-,构造函数,构造函数的作用:对对象的成员的初始化,构造函数的特性:,1,构造函数与类型名相同,2,当创建一个对象时 会被自动调用(仅调用一次),3,构造函数没有返回值类型,4.1,如果不提供构造函数 编译器则自动提供一个无参构造函数,4.2,但提供构造函数 编译器会自动回收默认的构造函数,4.3,缺省构造构造对基本类型不做初始化 类类型调用相应的缺,省,5,构造函数可以进行重载,6,构造函数的参数可以是默认值 ,但默认值必需靠右编写,一般可以通过 构造函数,参数的默认值,简化,构造函数的个数,对象的创建过程,1,为整个对象分配内存空间,2,以构造实参调用构造函数,2.1,构造基类部分 (无基类忽略),2.2,构造成员变量 (如果是类类型 则构建这个成员),2.3,执行构造代码 (函数只放在代码区),3,在栈中创建单个对象,类名 对象,;/,注意不加空括号,A a ;,类名 对象 (实参表),4,在栈中创建对象数组,类名 对象数组,元素个数,类名 对象数组,元素个数, = ,类名(实参表),;,类名 对象数组, = ,类名(实参表),;,A *arr10 = new A10A(1),A(2);,实现一个时钟类,初始化列表,类型转换构造,拷贝构造,初始化列表,析构,单参构造函数,day12,1,构造函数的初始化列表,A(int i): .i(i).,. m_i = i;,与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初,始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段,2,为什么使用初始化列表,初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行,赋值操作,/,2.1,常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面,2.2,引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要,写在初始化列表里面,2.3,成员变量的初始化顺序:按照成员定义的顺序进行初始化,(,与初始化表的,顺序无关,),2.4,类的类型成员变量和基类子对象必须在初始化列表中初始化,否则将调用,相应类型的缺省构造函数进行初始化(数组成员不能在列表中初始化),3,类型转换构造函数(单参构造函数),构造函数当其参数只有单个时 它还有另一种功能:类型转换,3.1,在目标类型中,可以接受单个源类型对象实参的构造函数,支持从源类型,到目标类型的隐式类型转换,class A A(int i,int j = 0,) A a = 100;,3.2,通过,explicit,关键字,可以强制这种通过构造函数实现的类型转换必须,显式地进行,4,析构函数,4.1,析构函数形式:,类名(),4.2,特点:无返回值,无参数,且不能重载,4.3,何时被调用:在销毁对象时,会自动调用,且仅被调用一次,(也可手调用),4.4,应用:一般用于对对象在构造过程或生命周期内所申请的资源内存,也可以执行其他类设计者所需要的最后使用对象之后的操作,(如没有动态分配内存,非必需定义析构函数),4.5,缺省析构函数,5.1,如果类中没有定义析构函数,编译器会提供一个缺省析构函数,5.2,缺省析构函数的特性:,5.2.1,对基本类型的成员变量不做任何操作,5.2.2,对类类型的成员变量和基类子对象,会调用相关的类型的析构,函数,6,对象的销毁过程,6.1,调用析构函数:执行析构函数,,析构成员变量,析构基类部分,6.2,释放整个对象所占用的内存空间,This,指针,常对象,This,指针与,const,关键字,day13,1 this,指针,1.1,概念:指向当前对象类型的指针,1.2,构造函数中,this,代表正在,“,被,”,构建的对象的地址,A a ;this = ,1.3,在成员函数中,this,代表调用这个函数的对象的地址,注意:,I this,是由编译器自动产生的,在类的成员函数中有效,II this,是一个常量,不允许对其赋值。,III,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会,自动将对象本身的地址作为一个隐含参数传递给函数,IV this,指针并不是对象本身的一部分,不会影响,sizeof,的结果,2 this,指针的应用,2.1,区分当一个类的某个成员变量与该类构造函数的相应参数取相同标识符,,在构造函数内部可以通过,this,指针将其区分,2.2,做函数的参数,2.3,做函数的返回值(串连调用),3,常对象,3.1,概念:用,const,修饰的对象叫常对象,3.2,作用:被,const,修饰的对象的数据成员不可以被改变,3.3,格式:, const,对象名 或,const ,对象名,const *,常对象指针名,const &,常对象引用名,注意:一 常对象只能调用(常函数(不可在常函数内修改成员变量,其实修饰,的是,this,指针,除非在成员函数被,mutable,(只能修饰成员变,量),二 非常对象可以调用(常函数)与(非常函数),三 原型相同的成员函数的常版本与非常版本可构成重载,(,匹配原则是:常对象只能选择常版本,非常对象优先非常版本,),常成员函数含义,:,通过该函数只能读取同一类中的数据成员的值,而不能修改它,常成员函数可不可以修改类外的变量?,析构函数,静态成员,拷贝函数与静态成员,day14,4,拷贝构造函数,4.1,函数形式:,class,类名,类名,(const,类名,& that) ,;,4.2,用于从一个已定义的对象构造其同类型的副本,A b = a,4.3,如果一个类没有定义拷贝构造函数,那么编译器会为其提供一个缺省拷贝,构造函数 (浅拷贝),4.3.1,缺省拷贝对基本类型成员变量,按字节复制,4.3.2,缺省拷贝对类类型成员变量和基类子对象,调用相应类型的拷贝构造,函数,4.3.3,如果自己定义了拷贝构造函数,编译器将不再提供缺省拷贝构造函数,,这时所有与成员复制有关的操作,都必须在自定义拷贝构造函数中编,写代码完成(深拷贝),4.3.4,若缺省拷贝构造函数不能满足要求,则需自己定义,4.3.4,拷贝构造的时机,4.3.4.1,用已定义对象作为同类型对象的构造实参,4.3.4.2,以对象的形式向函数传递参数,int fun(A i); A i = a;,4.3.4.3,从函数中返回对象,4.3.4.4,某些拷贝构造过程会因编译优化而被省略,注:所有系统定义的构造函数,其访问控制属性均为公有,(public),A,;,二,静态成员,static,7.1,静态成员,属于类,而,不属于对象,/,受类的,访问属性限制的全局变量或函数,特性:,1,静态成员变量不包含在对象实例中,生命期为整个程序,2,静态成员函数无,this,指针与常属性,/,3,静态成员与其他成员一样受访问控制的限制,7.2,静态成员的定义与初始化,静态成员只能在类的外部进行初始化,A a1 a2 static int i ;,7.3,所有该静态成员变量所属的类的对象共有静态成员,7.4,访问属性,1,静态成员函数只能访问静态成员,2,非静态成员函数可以访问静态成员,也可以访问静态成员,3,不使用对象也可以直接使用静态成员,静态成员可以看成是受类的访问属性控制的全局变量或全局函数,设计模式:单例模式,day15,一 单例模式:一个类只有一个实例(任务管理器),而且自行实例化并向整个系,统提供这个实例(最常用,最简单的模式),二 根据实例化对象的时机的不同分为两种:,1,饿汉式:程序启动便创建实例,/,2,懒汉式:调用时创建,三 优点:,1,内存中只有一个实例,节约内存,2,避免频繁创建销毁对象,提高性能,3,线程安全,成员指针,day16,1,成员指针:是用于对类中成员进行操作,1.1,定义格式:成员类型 类名,:*,指针名,=&,类名,:,成员名,int A:*pi;,1.2,使用形式:对象,.*,成员变量指针,A*pa = new a; pa-*pi ;,对象指针,-*,成员变量指针,1.3,与普通指针的区别:,普通指针用确定对象的地址进行初始化,指向一个确定的对象,成员指针用类的成员(是类的成员,而不是对象的成员)初始化(其本,质是记录了特定成员变量在对象实例中的相对地址,再解引用时,根据,调用对象的地址计算出成员变量的绝对地址),2,成员函数指针,2.1,定义格式,:,返回类型,(,类名,:*,成员函数指针,) (,形参表,);,成员函数指针,= &,类名,:,成员函数名,;,2.2,使用格式:,(,对象,.*,成员函数指针,) (,实参表,),(,对象指针,-*,成员函数指针,) (,实参表,),2.3,在调用成员函数指针时使用对象或对象指针的原因是传递,this,指针,3,静态成员指针(与普通指针并没有本质区别只是多了类的防控属性),3.1,定义格式,类型,*,静态成员变量指针,静态成员变量指针,= &,类名,:,静态成员变量,3.2,使用形式,*,静态成员变量指针,返回类型,(*,静态成员函数指针,) (,形参表,);,静态成员函数指针,=,类名,:,静态成员函数名,;,静态成员函数指针,(,实参表,),双目运算符,友元,二元操作符重载,day17,1,操作符重载概念:,在,C+,中,允许把已经定义的有一定功能的操作符进行重新定义,来完成更为,细致具体的运算等功能,运算符重载和函数重载都为简单的一类多态,2,重载目的:,c+,的面向对象的程序设计需要依赖类的特性,运算符重载的使用,使类类在使用普通运算符时变的更加容易,3,双目操作符的表达式:,L#R operator# a+b,重载形式,(,成员函数,),:,L.operator#(R) t1.operator+(TIME&t2) ,L,为调用对象,,R,为参数对象,重载形式,(,全局函数,),:,:operator#(L,R) operator+(t1,t2);,成员函数形式:,class LEFT,LEFT&operator#(const RIGHT&right),;,全局函数形式:,LEFT&operator#(LEFT&left,const RIGHT&right),4,友元函数,4.1,通过关键字,friend,可以将一个全局函数,或另一个类的成员函数,或,另一个类声明为某一个类的友元,Bfriend A ,4.2,友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,4.3,友元函数可以访问该类中的所有成员,4.4,友元函数不受类中访问权限限制,把声明放在类中哪里都可以,4.5,不是必要尽可能少用,因其破坏了面向对象的封装性,5,友元类,5.1,如果类,B,的成员需要频繁访问类,A,的数据成员,但因为访控属性的限制,,只能通过,A,的,public,函数进行操作,那么可以将,B,声明为,A,的友元类,这样就可以访问,A,中的未开放的数据成员,5.2,友元类,一个类可以做另一个类的友元类,5.3,声明方式,friend class,类名,;,5.4,注意事项,5.4.1,友元关系是单向的,5.4.2,友元关系不能被传递,5.4.3,友元关系不能被继承,自增运算符,输入输出运算符,一元操作符重载,day18,1,单目操作符表达式:,#o/o#,2,重载形式,2.1,重载形式(成员函数):,O.operator#() a.operator+(b),2.2,重载形式,(,全局函数):,:operator#(O) a+;,2.3,前自增减(操作数为左值,表达式的值为左值,且为操作数本身),class A/,成员函数形式,A&operator#(void),; Integer i1 ; +i1;,A&operator#(A&a)/,全局函数形式,2.4,后自增减(操作数为左值,表达式的值为右值,且为自增减以前的值),class A/,成员函数形式,const A operator#(int),;,const A operator#(A&a,int)/,全局函数形式,2.5,输出操作符:,(,左操作数为左值的输出流对象,右操作数为左值或右值,,表达式的值左操作数本身,)coutstudentendl;,如果重载以成员函数形式重载操作符,左操作,ostream,类为标准库提供且无,法添加新成员,那么只能以全局形式重载该操作符,重载形式(全局函数):,ostream&operator(,左操作数为左值的输入流对象,右操作数为左值,表达,式的值左操作数本身,),如果重载以成员函数形式重载操作符,左操作,istream,类为标准库提供且无,法添加新成员,那么只能以全局形式重载该操作符,istream& operator (istream& is, RIGHT& right) ,其他运算符重载,day19,1,操作符重载限制,1.1,无法重载的运算符:,作用域限定符(,:,),成员运算符(,.,),直接成员指针解引用运算符(,.* .-,),条件运算符(,?:,),字符长度操作符(,sizeof,),类型信息运算符(,typeid,),强制类型转换运算符(,const_cast),1.2,重载限制,重载后无法改变运算符的优先级与操作数的个数,不能重载非,c+,内置的运算符,$,new,delete,new ,delete ,智能指针,day20,1,智能指针的概念:是对变通指针进行类的封装,当智能指针离开作用域时,利,用类的机制对内部的普通指针指向的内存进行管理,foo()PA( new A(),2,作用:,/,内置类型,auto_ptr pa(new A) share_ptr pa-m_i;,相对于普通指针,当其离开作用域时指针本身将会释放,但指针指向的内,存却因为指针的释放而无法得到释放,而造成内存泄漏。,智能指针是封装了普通指针的类类型的对象,当其离开作用时自动执行的,析构函数负责了对普通指针指向的内存的释放,3,智能指针与普通指针的比较,3.1,智能指针重载了,“,*,”,,,“,-,”,运算符,;,3.2,一个对象只能有一个指向它的智能指针,而普通指针可以是多个,3.3,智能指针在做赋值时是以转义的形式实现(非深,/,浅拷贝赋值),3.3,智能指针不能用于对象的数组,autoptr A a = b,PointerA,A,operator *,A*operator-,return ,(,*this=A,),(,概念,语法,继承方式,继承,day21,访控属性,1,面向对象的特征:封装,继承,多态,2,封装:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只,让可信的类或者对象操作,对不可信的进行信息隐藏,3,继承:可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这,些功能进行扩展(类之间是,is-a,(,kind of,)的关系),4,基类与派生类:,4.1,基类(父类):被继承的类,4.2,派生类(子类):继承数据的类,5,继承的作用:,5.1,代码复用,5.2,功能扩展,6,语法,class,子类:继承方式,1,基类,1,,继承方式,2,基类,2 ;,7,继承方式,公有继承:,public,私有继承:,private,保护继承:,protected,8,公有继承的基本特点,8.1,访问属性:,a,子类中可以直接访问基类的所有公有和保护成员,b,子类中不可以直接访问基类的私有成员,8.2,名字隐藏:如果子类中有与基类中的公有或保护名字相同的成员,那么,子类的名字或隐藏所有基类中的同名成员,如果使用子类或通过子类访问基类的被子类隐藏的成员可以,利用,:,进行调用,9,继承方式与访问控制,因为子类的继承方式的不同,子类对访问基类时的访问控制属性也会发生变化,基类中 公有子类 保护子类 私有子类,-,公有成员 公有成员 保护成员 私有成员,保护成员 保护成员 保护成员 私有成员,私有成员 私有成员 私有成员 私有成员,注意:,1,子类访问基类成员的最大的权限,构造本类成员变量,-,执行构造代码,1.4,阻断继承:子类在构造基类子对象时无论如何都要调用基类中的构造函数,,如果需要子类无法实例化对象或子类无法被扩展,可以将基类的构造,函数的访问属性设定为私有,2.1,子类析构函数隐式调用基类析构函数,子类的析构函数在执行完其中的析构代码,并析构完所有的成员变量以后,,会,自动调用其基类的析构函数,,析构该子类对象中的基类子对象,(,基类析构函数不会调用子类析构函数,),通过基类指针析构子类对象,实际被析构的仅仅是子类对象中的基类子对象,,子类的扩展部分将失去被析构的机会,极有可能形成内存泄漏,2.2,子类对象的析构过程,执行析构代码,-,析构成员变量,-,析构基类子对象,拷贝构造函数,拷贝赋值运算符函数,继承中的操作符重载,继承中的拷贝构造与拷贝赋值,day23,1,拷贝构造函数,1.1,如果子类未定义拷贝构造函数,拷贝过程中的子类将,调用缺省,的,拷贝构造,,,其会自动调用其基类的拷贝构造函数,构造子类对象中的基类子对象,1.2,如果子类,已定义,拷贝构造函数,但,未显式指明基类部分的构造方式,则编译,器,还是,选择基类的,缺省,构造函数构造子类对象中的基类子对象,1.3,如果子类已定义拷贝构造函数,也显式指明了其基类部分以拷贝方式构造,则子类对象中的基类部分和扩展部分将一起被复制,2,拷贝赋值运算符函数,2.1,如果子类未定义拷贝赋值运算符函数,在触发拷贝赋值时会调用子类的缺,省拷贝赋值运算符函数,此函数会自动调用基类的拷贝赋值运算符函数,,复制子类中的基类子对象,2.2,如果子类定义了拷贝赋值运算符函数,但没有显式调用其基类的拷贝赋值,运算符函数,则子类对象中的基类子对象将得不到复制,2.3,如果子类定义了拷贝赋值运算符函数,且显示调用了其基类的拷贝赋值运,算符函数,,则子类对象中的基类部分和扩展部分一起被复制,3,继承中的操作符重载,在为子类提供操作符重载定义时,往往需要调用其基类针对该操作符所做的重,载定义,完成部分工作方法是:通过将子类对象的指针或引用向上造型为其基,类类型的指针或引用,可以迫使针对基类的操作符重载函数在针对子类的操作,符重载函数中被调用,4,私有子类和保护子类类型的指针或引用,不能隐式转换为其基类类型的指针或,引用,多重继承,内存分配,名字冲突,多重继承,day24,1,多重继承:一个类可以同时继承多个父类的行为和特征功能,2,多重继承的内存分布,2.1,多重继承中的子类会有多个基类子对象,他们依据继承的顺序由低地址到,高地址进行排列,2.2,构造函数也是由继承的顺序依次构造子类的基类子对象,2.3,析构函数则与构造的顺序相反,3,名字冲突,overload namehide B b ; A *pa= pa-fun(),在子类的多个基类中,如果在通过子类或在子类中访问多个基类中同名且并未,隐藏的标识符时,发有名字冲突。,可以通过作用域限定符显式指明所调用的基类标识符或用,using,指令来解决,钻石继承,钻石继承的问题,虚继承,钻石继承,day25,虚表,虚表指针,钻石继承:指一个子类继承自多个基类,且这些基类又继承自相同的基类,1,钻石继承的问题,派生多个中间子类的公共基类子对象,在继承自多个中间子类的汇聚子类对象,中,存在多个实例,在汇聚子类中,或通过汇聚子类对象,访问公共基类的成,员,会因继承路径的不同而导致不一致,2,钻石问题的解决方式,通过虚继承,可以保证公共基类子对象在汇聚子类对象中,仅存一份实例,,且为多个中间子类子对象所共享,3,虚继承,虚继承:,继承定义中包含了,virtual,关键字的继承关系,虚基类: 在虚继承体系中的通过,virtual,继承而来的基类,3.1,在继承链最末端的子类的构造函
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!