CC++国嵌学习笔记_第1页
CC++国嵌学习笔记_第2页
CC++国嵌学习笔记_第3页
CC++国嵌学习笔记_第4页
CC++国嵌学习笔记_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1、在学习内核驱动奥秘多嵌入式内核制作时,make uImage ARCH=arm CROSS_COMPILE=arm-linux- 后,linux目录下买有出现uImage.bin 2、 mini2440没有加根文件系统时启动内核出现Data Abort(从30008000启动时出现的)3、 mini2440加了根文件系统时启动内核出现Data AbortLs 之后并没有出现制作的根文件系统若从30008040启动后正常,(加了一个头的原因?)4、 字符驱动设计时:mknod只能用 mknod /dev/memdev0 . . .若改为mknod /dev/memdev1. . .或其它则不

2、能出现预期的效果-和相应的应用程序向对应fd = open("/dev/memdev0",O_RDWR);5、 进入linux内核之后修改开发板ip需修改两个文件中的相关ip,gateway,dns为指定:/etc/init.d/eth0-ifconfig/etc/eth0-setting6、7、APCS,ARM 过程调用标准(ARM Procedure Call Standard),提供了紧凑的编写例程的一种机制,定义的例程可以与其他例程交织在一起。最显著的一点是对这些例程来自哪里没有明确的限制。它们可以编译自 C、 Pascal、也可以是用汇编语言写成的。APCS 对我

3、们通常称为 R0 到 R14 的寄存器起了不同的名字。使用汇编器预处理器的功能,你可以定义 R0 等名字,但在你修改其他人写的代码的时候,最好还是学习使用 APCS 名字。 寄存器名字 Reg # APCS 意义 R0 a1 工作寄存器 R1 a2 " R2 a3 " R3 a4 " R4 v1 必须保护 R5 v2 " R6 v3 " R7 v4 " R8 v5 " R9 v6 " R10 sl 栈限制 R11 fp 桢指针 R12 ip R13 sp 栈指针 R14 lr 连接寄存器 R15 pc 程序计数器

4、译注:ip 是指令指针的简写。 8、 ftp环境的搭建安装、配置、重启#C语言学习笔记#1、 基本数据类型分析什么是数据类型?? 数据类型可以理解为固定内存大小的别名? 数据类型是创建变量的模子变量的本质? 变量是一段实际连续存储空间的别名? 程序中通过变量来申请并命名存储空间? 通过变量的名字可以使用存储空间2、 auto ,register ,static 分析?static修饰的局部变量存储在程序静态区?static的另一个意义是文件作用域标示符 -修饰函数作用域只是声明的文件中,修饰的全局变量作用域只是声明的文件中?register变量的必须是CPU寄存器可以接受的值?不能用&

5、运算符获取register变量的地址?auto变量存储在程序的栈中,默认属性? static变量存储在程序静态区中(静态全局变量)? register变量请求存储于CPU寄存器中3、 if ,switch ,do , while , for分析if语句中零值比较的注意点? bool型变量应该直接出现于条件中,不要进行比较? 普通变量和0值比较时,0值应该出现在比较符号左边? float型变量不能直接进行0值比较,需要定义精度 #define EPSINDN 0.00000001 ,float f=0.0 if(-EPSINDN <=f)&&(f<=EPSINDN )

6、 break和continue的区别? break表示终止循环的执行? continue表示终止本次循环体,进入下次循环执行4、 goto ,void ,extern , sizeof分析goto 破坏了过程式程序设计的规则 void指针的意义? C语言规定只有相同类型的指针才可以相互赋值? void*指针作为左值用于“接收”任意类型的指针? void*指针作为右值赋值给其它指针时需要强制类型转换?Void* 指针实现memset函数 void memset(void*p ,char v ,int size) 接收任意类型的数组值? extern用于声明外部定义的变量和函数? extern用于

7、“告诉”编译器用C方式编译 extern “C” 为sizeof正名? sizeof是编译器的内置指示符,不是函数? sizeof用于“计算”相应实体所占的内存大小(字节)? sizeof的值在编译期就已经确定5、 const 和volatile 的分析const修饰变量(现代C编译器中和标准C中)? 在C语言中const修饰的变量是只读的,其本质还是变量? const修饰的变量会在内存占用空间? 本质上const只对编译器有用,在运行时无用const修饰指针号 -口诀(以*为界):左数(数据内容)右指(指针) (不可改变)const修饰函数参数和返回值? const修饰函数参数表示在函数体内

8、不希望改变参数的值? const修饰函数返回值表示返回值不可改变,多用于返回指针的情形深藏不漏的volatile? volatile可理解为“编译器警告指示字”? volatile用于告诉编译器必须每次去内存中取变量值? volatile主要修饰可能被多个线程访问的变量? volatile也可以修饰可能被未知因数更改的变量const表示我们自己的代码不会改变这个值(别的代码或者硬件有可能改变这个值)。volatile表示禁止优化。因为编译器会认为如果代码没有改变变量,那么这个变量就不会改变,因此编译器会用寄存器把该变量缓存起来,每次需要读取变量值的时候,就从缓存中读取。这在大多数时候是正确的,

9、但是在多线程或者中断的场合就不正确了6、 struct 和union分析struct空结构体占内存大小在编译器实现上的不同由结构体产生柔性数组 -斐波那契数列? 柔性数组即数组大小待定的数组? C语言中结构体的最后一个元素可以是大小未知的数组? C语言中可以由结构体产生柔性数组union和struct的区别? struct中的每个域在内存中都独立分配空间? union只分配最大域的空间,所有域共享这个空间union使用的注意事项? union的使用受系统大小端的影响,也可以利用其特性判断系统的大小端7、 enum和typedef分析一种自定义类型? enum默认常量在前一个值的基础上依次加1?

10、 enum类型的变量只能取定义时的离散值枚举类型和#define的区别?#define宏常量只是简单的进行值替换,枚举常量是真正意义上的常量?#define宏常量无法被调试,枚举常量可以?#define宏常量无类型信息,枚举常量是一种特定类型的常量typedef的意义?typedef用于给一个已经存在的数据类型重命名? typedef并没有产生新的类型? typedef重定义的类型不能进行unsigned和signed扩展typedef和#define的区别? typedef是给已有类型取别名? #define为简单的字符串替换,无别名的概念8、 注释符号注释规则小结? 编译器会在编译过程删除

11、注释,但不是简单的删除而是用空格代替? 编译器认为双引号括起来内容都是字符串,双斜杠也不例外? “/*/”型注释不能被嵌套你觉得Y=x/*p是什么意思?作者本意:把x除以*p的结果赋值给y编译器:将/*作为一段注释的开始,把/*后的内容都当成注释内容,直到*/出现为止出色的注释你来写? 注释应该准确易懂,防止二义性,错误的注释有害而无利? 注释是对代码的提示,避免臃肿和喧宾夺主? 一目了然的代码避免加注释? 不要用缩写来注释代码,这样可能会产生误解? 注释用于阐述原因而不是用于描述程序的运行过程9、接续符和转义符10、 单引号和双引号11、 逻辑运算符使用分析&& | !12、

12、 位运算符分析& | << >>防错准则C语言中 << 是逻辑移位,不是循环移位。1 左移 32 位后为 0,左移 -1 位实际是左移 255 位(互补),当然也是0。13、 + -操作符使用分析贪心法 - > +, -表达式的阅读技巧? 编译器处理的每个符号应该尽可能多的包含字符? 编译器以从左向右的顺序一个一个尽可能多的读入字符? 当即将读入的字符不可能和已读入的字符组成合法符号为止14、 优先级和类型转换分析C语言隐式类型转换? 算术运算式中,低类型转换为高类型? 赋值表达式中,表达式的值转换为左边变量的类型? 函数调用时,实参转换为形参

13、的类型? 函数返回值,return表达式转换为返回值类型15、 编译过程简介16、 宏定义与使用分析定义宏常量? #define定义宏常量可以出现在代码的任何地方,没有作用域问题? #define从本行开始,之后的代码都可以使用这个宏常量定义宏表达式? #define表达式给有函数调用的假象,却不是函数? #define表达式可以比函数更强大? #define表达式比函数更容易出错宏表达式与函数的对比? 宏表达式在预编译期被处理,编译器不知道宏表达式的存在? 宏表达式用“实参”完全替代形参,不进行任何运算? 宏表达式没有任何的“调用”开销? 宏表达式中不能出现递归定义定义日志宏强大的日志宏17

14、、 条件编译使用分析条件编译的意义?使得我们可以按不同的条件编译不同的代码段,因而可以产生不同的目标代码? #if#else#endif被预编译器处理;而ifelse语句被编译器处理,必然被编译进目标代码? 实际工程中条件编译主要用于一下两种情况:? 不同的产品线共用一份代码? 区分编译产品的调试版和发布版18、 #error和#line? #error用于生成一个编译错误消息,并停止编译? 用法? #line用于强制指定新的行号和编译文件名,并对源程序的代码重新编号? 用法19、 #pragma预处理分析#pragma简介? #pragma是编译器指示字,用于指示编译器完成一些特定的动作?

15、#pragma所定义的很多指示字是编译器和操作系统特有的? #pragma在不同的编译器间是不可移植的? 预处理器将忽略它不认识的#pragma指令? 两个不同的编译器可能以两种不同的方式解释同一条#pragma指令#pragma message? message参数在大多数的编译器中都有相似的实现? message参数在编译时输出消息到编译输出窗口中? message可用于代码的版本控制#pragma pack - 能改变编译器的默认对齐方式?什么是内存对齐?不同类型的数据在内存中按照一定的规则排列;而不是顺序的一个接一个的排放,这就是对齐。为什么需要内存对齐?? CPU对内存的读取不是连续

16、的,而是分成块读取的,块的大小只能是1、2、4、8、16字节 (起始地址%对齐数)? 当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣? 某些硬件平台只能从规定的地址处取某些特定类型的数据,否则抛出硬件异常Struct 占用内存的大小第一个成员起始于0偏移处每一个成员按其类型大小和指定对其参数n中较小的一个进行对齐偏移地址和成员占用大小均需对齐(除尽)结构体成员的对齐参数为其所有成员使用的对齐参数的最大值结构体总长度必须为所有对其参数的整数倍#pragma pack(8)Struct S1short a; long b;Struct S2char c;struct S1

17、 d; doublt e;20、21、22、 #和#运算符使用解析?#运算符用于在预编译期将宏参数转换为字符串?#运算符用于在预编译期粘连两个符号23、 指针基础不能类型的指针占用的内存空间大小相同指针是C语言中一种特别的变量24、 数组基础数组的概念,大小,地址与数组名?数组名在大多数情况下被当成常量指针处理,数组名其实并不是指针,在外部声明时不能混淆25、 数组与指针分析数组的本质? 数组是一段连续的内存空间? 数组的空间大小为sizeof(array_type) * array_size? 数组名可看做指向数组第一个元素的常量指针指针是一种特殊的变量,与整数的运算规则为p + n; &l

18、t;-> (unsigned int)p + n*sizeof(*p);(当p指针指向同类型的数组)指针的运算(同类型的指针之间的减法),指针的比较数组的访问:以下标的形式,以指针的形式a和&a的区别 (在二维数组中表现尤为明显)?a和&a的意义不同其区别在于指针运算a + 1->(unsigned int)a + sizeof(*a)&a + 1->(unsigned int)(&a) + sizeof(*&a)26、 C语言中的字符串?从概念上讲,C语言中没有字符串数据类型? 在C语言中使用字符数组来模拟字符串? C语言中的字符串是

19、以0结束的字符数组? C语言中的字符串可以分配于栈空间,堆空间或者只读存储区字符串长度 (strlen()返回值为无符号整形)长度不受限的字符串?字符串复制:char* strcpy(char* dst, const char* src);?字符串连接:char* strcat(char* dst, const char* src);?字符串比较:int strcmp(const char* s1, const char* s2);长度受限的字符串 (0)27、 指针数组和数组指针分析数组指针?C语言中通过typedef为数组类型重命名typedef type(name)size;?可通过数组

20、类型定义数组指针:ArrayType* pointer也可以直接定义:type (*pointer)n;指针数组 指针数组的定义:type* pArrayn;命令行参数的使用 int main(int argc, char* argv, char* env)28、 多维数组和多维指针29、 数组参数和指针参数分析C语言中的数组参数会退化为指针30、 函数与指针分析? C语言中通过typedef为函数类型重命名typedef type name(parameter list)?函数指针可通过函数类型定义函数指针: FuncType* pointer;?函数指针也可以直接定义:type (*poi

21、nter)(parameter list);回调函数指针阅读技巧31、 动态内存分析为什么使用动态内存分配? C语言中的一切操作都是基于内存的? 变量和数组都是内存的别名,如何分配这些内存由编译器在编译期间决定Malloc 和free ; calloc(以类型的大小为单位申请内存) 和 realloc(重置类型的大小)32、 程序中的三国天下栈保存了一个函数调用所需的维护信息? 函数参数,函数返回地址? 局部变量? 函数调用上下文程序中的堆?堆的出现为了解决 -栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组系统对堆空间的管理方式? 空闲链表法,位图法,对象池法等等程序中的

22、静态存储区33、 程序的内存布局程序的内存布局;文件的布局在内存中的映射34、 野指针和内存操作分析初识野指针? 野指针通常是因为指针变量中保存的值不是一个合法的内存地址而造成的? 野指针不是NULL指针,是指向不可用内存的指针? NULL指针不容易用错,因为if语句很好判断一个指针是不是NUL野指针的由来?变量没有被初始化 ,结构体成员指针未初始化或没有分配足够的内存,内存分配成功但没有初始化? 使用已经释放过后的指针? 指针所指向的变量在指针之前被销毁内存越界与内存泄露分析C语言中的交通规则? 用malloc申请了内存之后,应该立即检查指针值是否为NULL,防止使用值为NULL的指针? 牢

23、记数组的长度,防止数组越界操作,考虑使用柔性数组? 动态申请操作必须和释放操作匹配,防止内存泄露和多次释放? free指针之后必须立即赋值为NULL35、 认清函数的真面目语言中的顺序点? 每个完整表达式结束时? &&, |, ?:, 以及逗号表达式的每个运算对象计算之后? 函数调用中对所有实际参数的求值完成之后(进入函数体之前)36、 可变参数分析与宏分析<stdarg.h> va_listva_start va_end va_arg?可变参数必须从头到尾按照顺序逐个访问? 参数列表中至少要存在一个确定的命名参数? 可变参数宏无法判断实际存在的参数的数量? 可变参

24、数宏无法判断参数的实际类型37、 函数调用行为活动记录是函数调用时用于记录一系列相关信息的记录? 临时变量域:用来存放临时变量的值,如k+的中间结果? 局部变量域:用来存放函数本次执行中的局部变量? 机器状态域:用来保存调用函数之前有关机器状态的信息,包括各种寄存器的当前值和返回地址等;? 实参数域:用于存放函数的实参信息? 返回值域:为调用者函数存放返回值调用约定就是描述参数是怎么传递到栈空间的,以及栈空间由谁维护38、 函数递归与函数设计技巧#C语言学习笔记#C+语言学习笔记#1、 C到C+的升级C+继承了所有的C特性C+在C的基础上提供了更多的语法和特性C+的设计目标是运行效率与开发效率

25、的统一C+中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义register关键字的变化register关键字请求“编译器”将局部变量存储于寄存器中C语言中无法取得register变量地址在C+中依然支持register关键字C+编译器有自己的优化方式,不使用register也可能做优化C+中可以取得register变量的地址在C语言中,重复定义多个同名的全局变量是合法的在C+中,不允许定义多个同名的全局变量C+编译器对const常量的处理当碰见常量声明时在符号表中放入常量编译过程中若发现使用常量则直接以符号表中的值替换编译过程中若发现对const使用了extern或者&操作

26、符,则给对应的常量分配存储空间C语言中const变量是只读变量,有自己的存储空间C+中的const常量可能分配存储空间当const常量为全局,并且需要在其它文件中使用当使用&操作符取const常量的地址Const和宏的相似之处与区别Struct类型的加强(是否是一个新的内存)C+中所有的变量和函数都必须有类型,C语言中的默认类型在C+中是不合法的C和C+中关于void f() ,void f(void) 的区别bool类型是C+新增加的基础类型,其值只能是true和false2、 C+中的引用C+中的引用可以看作变量的别名来使用C+中的常引用可以使得一个变量拥有只读属性C+中的常引用可

27、以用常量初始化而得到一个只读变量C+中引用的本质是一个指针常量(内部实现,占用空间大小)当函数返回值为引用时:若返回栈变量,不能成为其它引用的初始值,不能作为左值使用;若返回静态变量或全局变量,可以成为其他引用的初始值,即可作为右值使用,也可作为左值使用三目运算符的升级(左操作数)3、 函数的升级内联函数:C+编译器可以将一个函数进行内联编译,被C+编译器内联编译的函数叫做内联函数,内联函数在最终生成的代码中是没有定义的,C+编译器直接将函数体插入函数调用的地方,内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)g+中的_attribute_(always_inline)属性C+中内联编

28、译的限制:C+中内联函数的实现机制:符号表函数默认参数:规则在C+中可以为函数提供占位参数(只有函数类型声明,没有函数名的声明。存在的意义)函数重载:编译器调用重载函数的准则,将所有同名函数作为候选者,尝试寻找可行的候选函数,同时(取决于编译器的设计):(优先级)精确匹配实参,通过默认参数能够匹配实参,通过默认类型转换匹配实参;匹配失败,最终寻找到的可行候选函数不唯一,则出现二义性,编译失败。无法匹配所有候选者,函数未定义,编译失败。函数重载是由函数名和参数列表决定的。C和C+的相互调用:extern _cplusplus4、 新的关键字Type* pointer =new Type dele

29、te ;Type* pointer = new TypeNew 和malloc命名空间的定义和使用强制类型转换:static_cast const_cast dynamic_canst reinterpret_cast 用法:xxx_cast< Type >( Expression )5、 专题一经典问题分析const和引用的疑惑:符号表。只有用字面量初始化的const常量才会进入符号表,对const常量进行引用会导致编译器为其分配空间,虽然const常量被分配了空间,但是这个空间中的值不会被使用,使用其它变量初始化的const常量仍然是只读变量;被volatile修饰的const

30、常量不会进入符号表,退化为只读变量,每次访问都从内存中取值const引用的类型与初始化变量的类型:相同:使初始化变量成为只读变量不同:生成一个新的只读变量,其初始值与初始化变量相同引用与指针的疑惑:指针与引用的区别:指针是一个变量,其值为一个内存地址,通过指针可以访问对应内存地址中的值,引用只是一个变量的新名字,所有对引用的操作(赋值,取地址等)都会传递到其引用的变量上,指针可以被const修饰成为常量或者只读变量,const引用使其引用的变量具有只读属性,指针就是变量,不需要初始化,也可以指向不同的地址,引用天生就必须在定义时初始化,之后无法在引用其它变量。如何理解“引用的本质就是指针常量”

31、?重载的疑惑:C+编译器对字面量的处理方式,当使用字面量对变量进行初始化或赋值时(?溢出?);深入理解重载规则(实参为变量字面量)C方式编译的疑惑:C方式的编译主要指按照C语言的规则对函数名进行编译,函数名经过编译后可能与源码中的名字有所不同,C+编译器为了支持重载,函数名经过编译后会加上参数信息,因而编译后的函数名与源码中完全不同,C编译器不会在编译后的函数名中加上参数信息6、 类中的封装类的精华在于封装将实现细节和使用方式相分离C+中通过public和private实现类的封装struct(默认public),class(默认private)public成员可以通过变量被外界访问priva

32、te成员只能够在类内部使用类的定义和实现可以分开到不同的文件中7、构造与析构对象初始化的不同解决方案的引出构造函数的定义(类成员函数),调用(有时编译器自动,有时手动)构造函数可以重载,并遵守重载规则两个特殊的构造函数(编译器可默认提供):无参构造函数,拷贝构造函数(在默认情况下,仅进行值的复制)C+中提供了初始化列表对成员变量进行初始化(规则)(初始化与赋值的区别)类中的const成员是肯定会被分配空间的,类中的const成员变量只是一个只读变量对象的销毁的不同解决方案的引出构造函数与析构函数的调用次序:当类中有成员变量是其它类的对象时,首先调用成员变量的构造函数,调用顺序与声明顺序相同,之

33、后调用自身类的构造函数,析构函数的调用秩序与对应的构造函数调用秩序相反构造函数的调用时机8、 类的静态成员在C+中可以定义静态成员变量和静态成员函数,静态成员属于整个类所有,不需要依赖任何对象,可以通过类名直接访问public静态成员,可以通过对象名访问public静态成员,静态成员函数可以直接访问静态成员变量静态成员变量的定义:在定义时直接通过static关键字修饰,静态成员变量不依赖于任何对象,需要在类外单独分配空间,语法规则:Type ClassName:VarName;静态成员函数的定义:在定义时直接通过static关键字修饰,其余部分与普通成员函数定义相同。C+对象模型初探:+类对象

34、中的成员变量和成员函数是分开存储。成员变量:普通成员变量:存储于对象中,与struct变量有相同的内存布局和字节对齐方式静态成员变量:存储于全局数据区中。成员函数:存储于代码段中静态成员函数不包含隐藏的this指针9、 操作符重载C+中操作符重载的本质:C+中通过operator关键字可以利用函数扩展操作符,operator的本质是通过函数重载实现操作符重载C+中的类的友元:private声明使得类的成员不能被外界访问,但是通过friend关键字可以例外的开放权限操作符重载遵循函数重载的规则用全局函数与用成员函数重载的操作符:当无法修改左操作数的类时,使用全局函数进行重载;=, , ()和-&

35、gt;操作符只能通过成员函数进行重载C+编译器会为每个类提供默认的赋值操作符,默认的赋值操作符只是做简单的值复制,类中存在指针成员变量时就需要重载赋值操作符C+中通过一个占位参数来区分前置运算和后置运算不要重载&&和|操作符10、 专题二经典问题解析malloc与free和new与delete有什么区别?:malloc和free是库函数,以字节为单位申请堆内存,new和delete是关键字,以类型为单位申请堆内存,malloc和free单纯的对内存进行申请与释放,对于基本类型new关键字会对内存进行初始化,对于类类型new和delete还负责构造函数和析构函数的调用编译器对构造

36、函数的调用:C+编译器会尝试各种手段尝试让程序通过编译方式一:尽力匹配重载函数,方式二:尽力使用函数的默认参数,方式三:尽力尝试调用构造函数进行类型转换C+提供了explicit关键字用于阻止编译器对构造函数的调用尝试一个类最多只能有一个对象存在于系统中,如何实现?无状态函数:函数的调用结果只与实参值相关;状态函数:函数的调用结果不仅与实参值相关还与之前的函数调用有关11、 惊艳的继承面向对象中的继承指类之间的父子关系子类拥有父类的所有成员变量和成员函数,子类就是一种特殊的父类,子类对象可以当作父类对象使用,子类可以拥有父类没有的方法和属性C+中的访问级别与继承:public,private,

37、protected12、 继承的构造与析构赋值兼容性原则子类对象可以当作父类对象使用,子类对象可以直接赋值给父类对象,子类对象可以直接初始化父类对象,父类指针可以直接指向子类对象,父类引用可以直接引用子类对象继承对象模型类在C+编译器的内部可以理解为结构体,子类是由父类成员叠加子类新成员得到的继承与构造在子类对象构造的时候需要调用父类构造函数对其继承得来的成员进行初始化,在子类对象析构的时候需要调用父类析构函数对其继承得来的成员进行清理。子类对象在创建时会首先调用父类的构造函数,父类构造函数执行结束后,执行子类的构造函数,当父类的构造函数有参数时,需要在子类的初始化列表中显示调用,析构函数调用

38、的先后顺序与构造函数相反继承与组合的混搭构造函数的调用:口诀->先父母,后客人,再自己同名成员变量子类依然从父类继承同名成员,在子类中通过作用域分别符:进行同名成员区分,同名成员存储在内存中的不同位置13、 多态与继承 函数重写在子类中定义与父类中原型相同的函数,函数重写只发生在父类与子类之间,父类中被重写的函数依然会继承给子类,默认情况下子类中重写的函数将隐藏父类中的函数,通过作用域分辨符:可以访问到父类中被隐藏的函数当函数重写遇上赋值兼容性原则(问题):C+与C相同,是静态编译型语言;在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象,所以编译器认为父类指针指向的是父类对

39、象(根据赋值兼容性原则,这个假设合理);由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象;从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数多态的本质面向对象的新需求引出。C+中通过virtual关键字对多态进行支持,使用virtual声明的函数被重写后即可展现多态特性重写与重载函数重载:必须在同一个类中进行,子类无法重载父类的函数,父类同名函数将被覆盖,重载是在编译期间根据参数类型和个数决定调用函数函数重写:必须发生于父类与子类之间,并且父类与子类中的函数必须有完全相同的原型,使用virtual声明之后能够产生多态,多态是在运行期间

40、根据具体对象的类型决定调用函数是否可以将类的每个成员函数都声明为虚函数?多态的实现原理:当类中声明虚函数时,编译器会在类中生成一个虚函数表,虚函数表是一个存储类成员函数指针的数据结构,虚函数表是由编译器自动生成与维护的,virtual成员函数会被编译器放入虚函数表中,存在虚函数时,每个对象中都有一个指向虚函数表的指针。通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。对象中的VPTR指针什么时候被初始化?对象在创建的时候由编译器对VPTR指针进行初始化,只有当对象

41、的构造完全结束后VPTR的指向才最终确定,父类对象的VPTR指向父类虚函数表,子类对象的VPTR指向子类虚函数表(构造函数中的虚函数)纯虚函数抽象类与纯虚函数 virtual double area () = 0; class shape;14、 专题三经典问题解析当多态遇见对象数组会发生什么?不要将多态应用于数组。 指针运算是通过指针的类型进行的, 多态通过虚函数表实现的为什么没有讲解多重继承?C+在语法上直接支持多重继承,被实际开发经验抛弃的多继承(便利大于不便,不易维护,可用单继承解决)。C+中对多继承二义性的解决方案:虚继承(class P1:virtual class Object

42、, class P2:virtual class Object)从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝。C+是否有Java中接口的概念?绝大多数面向对象语言都不支持多继承,绝大多数面向对象语言都支持接口的概念, C+中没有接口的概念,C+中可以使用纯虚函数实现接口。接口只是功能的说明,并不是功能的实现。15、 函数模板从C+中如何交换两个变量的值的函数重载说起(代码复用)泛型编程函数模板:语法规则 template <typename T>函数模板的应用:自动类型推导调用;具体类型显示调用编译器并不是把函数模板处理成能够处理任意类型的函数 编译器从函数模板通过具体

43、类型产生不同的函数 编译器会对函数模板进行两次编译在声明的地方对模板代码本身进行编译在调用的地方对参数替换后的代码进行编译具体类型显示调用函数模板与重载C+编译器优先考虑普通函数;如果函数模板可以产生一个更好的匹配,那么选择模板;可以通过空模板实参列表的语法限定编译器只通过模板匹配,注意事项:函数模板不允许自动类型转化,普通函数能够进行自动类型转换多参数函数模板:(自动类型模板推导?不完美的解决方案)16、 类模板声明的泛指类型 T 可用于声明成员变量和成员函数, 编译器对类模板的处理方式和函数模板相同, 编译器从类模板通过具体类型产生不同的类 编译器在声明的地方对类模板代码本身进行编译 编译

44、器在使用的地方对参数替换后的代码进行编译(生成代码)类模板的工程应用(.h .hpp)类模板的特化:用template<>声明一个类时,表示这是一个特化类!Template<> class<int>特化特模板的意义类模板的局部特化(为什么不用新类?)非类型模板参数限制:变量不能作为模板参数,浮点数和类对象不能作为模板参数,全局指针不能作为模板参数工程中的内存问题:智能指针智能指针是一个类模板,通过构造函数接管申请的堆内存通过析构函数确保堆内存被及时释放,通过重载指针运算符 * 和 -> 模拟指针的行为,通过重载比较运算符 = 和 != 模拟指针的比较17、 STL简介主要组成:容器:容器中存放的都必须是值而不能是引用,容器内部

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论