C++知识点总结


第一章 类: 1. 类的两种定义形式: (1)在类中定义成员函数; (2)在类之后定义成员函数(类定义的文件为(头文件),类成员函数的实现为另一个 文件)。 2. class 和 struct 的区别: (1)C 中的 struct 与 C++中 struct 的区别:  C 的 struct 没有方法,而 C++的 struct 可以有方法 //即函数  C 的 struct 中成员没有访问控制权限,C++的 class 则有,且默认 private  C 的 struct 不能为空,而C++的 struct 则可以为空,大小为 1。  C 的 struct 是在定义的时候就给数据成员开辟了空间,C++的 class 是在定义类 对象的时候才开辟的空间,virtual 会加上 4 个字节的空间(不限个数), (2)C++中 class 与 struct 的区别: class 中成员默认的访问控制权限是 private,而 struct 则默认的是 public 3. 类:类是一种抽象的数据结构,用来描述对象的属性,是将不同数据类型的数据以 及与这些数据相关的操作封装在一起的集合体。(封装性) 4. 面向过程与面向对象程序设计的不同: (1)过程是基于算法的,而对象是基于类的; (2)过程是以函数(过程)的设计来实现的,而对象是以类的设计来实现的; (3)过程通过数据流图(流程图)来体现的,而对象是通过类图(用例图)来体现的; (4)过程需要将步骤一步一步的具体化,而对象则只注重类的设计,不管实现方法。 5. 面向对象的四大特点:抽象、封装、继承、多态 6. OOP:面向对象编程 OOD:面向对象设计 OOA:面向对象分析 OOI:面向对象接口 7. 内联函数(inline): (1)将类中的语句只有 1~5 句的且没有 swith 语句的成员函数一般称为内联函数,用 in line 标示。内联函数在运行时在源程序中原地扩展.(在类中定义的成员函数一般被默认为 内联函数) (2) 内联与预处理的区别: ○1 宏是预处理命令,in line则是个函数 ○2 宏是在预编译时进行替换,而in line在执行到这一句时才替换 ○3 宏在替换时不做类型检测,而in line则要做类型检测 ○4 宏会出现二义性,in line则不会出现 ○5 (3)内联函数节省了调用时间,但增加了存储空间 宏占编译时间,in line则占运行时间 普通函数节省了存储空间,但增长了调用时间 8. 一个类的对象所占空间的大小由它的数据成员所占据的空间总和决定;当类有 virtual 函数时,再加上 4 个字节的大小。 9.访问控制权限: (1)public 公有型:外部可以访问 (2)protected 保护型:除了本类、子类与友元可访问外其它的都不能访问 (3)private 私有型:除了本类外,外部的都不能访问 10.成员访问控制权限的设计: (1)成员函数: ○1 如果为了外部调用,就声明为public ○2 如果为了完成一些内部辅助功能,就声明为private ○3 (2)数据成员: 如果类会被继承,则应该声明为protected ○1 原则上不能有public ○2 如果类不会被继承,则声明为 private ○3 如果会被继承,则声明为protected 11. this 指针:指向当前对象,其作用为: (1)对于非静态成员函数,隐含的 this 指针作为当前对象的地址成为第一个传递参数 (2)可用于访问被同名局部变量屏蔽的类的数据成员 (3)从成员函数返回当前对象的引用 第二章 构造函数 1. 类与对象的区别: (1) 二者的定义不同:类是不同类型数据及其相关操作的集合,对象则是类的实例化 (2) 类是个类型,不占空间,但对象占空间。 (3)类是类型而不是数据对象,每个类的对象都是该类数据成员的拷贝 2. 构造函数: (1) 构造函数的作用:专门用于创建对象为其开辟空间并初始化其数据成员 (2) 构造函数可以重载,但不能有返回值,不能随意被调用,可通过“类名::”强制调用 (3) 默认构造只负责分配空间,不做初始化工作。 (4) 自定义构造函数(带参构造)作用过程:声明时分配空间,按数据成员声明顺序初始 化之,并进入该函数体进行赋初值操作。一旦自定义了带参构造,一般还要自定义默 认构造 (5) 缺省构造:结合默认构造与带参构造 如 A(int i=0, int j=0) {}其中的“=0”只在声明时写 (6)如果定义的对象是全局对象或静态对象,则对象的位模式全为 0 ,否则对象值是随 机的 (7)若对象为数组时,类中则必须有默认构造或缺省构造 (8) 如果给数据成员动态开辟了空间就必须释放,new 对应 delete。数组时 delete []; 3. 冒号语法(初始化列表): (1)针对于数据成员中有类对象的类(组合),当然一般类型的类成员也可以应用 (2)按照数据成员的声明定义顺序,用冒号语法后面括号中的值初始化数据成员(在{} 内容执行,即在基类执行前执行!)(先执行子类的构造函数,不传参,在执行基类的构造函 数,完了之后回到子类,传参然后冒号语法,在然后才是构造函数{}里面语句的执行) (3)冒号语法使得常量数据成员与引用数据成员的初始化成为可能。因为常量是不能被 赋值的,一旦初始化后其值就不能再改变了,引用成员也是不可重新指派的,初始化后其值 也就固定不变了,所以常量和引用的初始化必须放在构造函数的冒号后面 如下的用法: Class sillyc lass { Public: sillyc lass(int &i):ten(10),refr(i); Protected: const int ten; int &refr; } 4. 构造对象的顺序: 程序并不是根据运行顺序来决定变量定义的顺序,而是所有的变量和对象都在函数开始执 行时统一定义,统一定义的顺序正是这些变量和对象在函数中出现的顺序。 (1) 局部和静态对象以声明的顺序构造 (2) 静态对象只被构造一次,即静态对象只在首次进入到定义该静态对象函数时构造,以 后再进入时不再构造 (3) 所有全局对象都在主函数开始之前被构造,构造时没有特殊的顺序 (4) 成员以其在类中声明的顺序构造 5. 析构函数: (1) 如果一个构造函数从堆中分配了内存,则这块内存在对象消失前必须被释放掉 (2) 析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意被调 用,也没有重载,在类对象生命期结束时由系统自动调用,也称为逆构造 (3) 析构以调用构造函数的相反顺序被调用:即先析构后定义的对象,再析构先定 义的对象 (4) 每个类有且只有一个析构函数 第三章 堆与拷贝构造 1. C++ 的内存布局: (1)全局数据区 (2)代码区 (3)栈区 (4)堆区(自由存储区) (5)常量存储区 2.全局变量、静态数据、常量存放在全局数据区,所有类成员函数和非成员代码存放在代 码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区,余 下的空间作为堆区 3.堆空间的存在意义: (1)直到运行时才能知道需要多少对象空间 (2)不知道对象的生存期到底有多长 (3)直到运行时才知道一个对象需要多少内存空间 (4)减少局部变量对空间的占有 4.从堆上分配对象数组时,只能调用默认构造或缺省构造 5. malloc /free 与 new /delete 的区别点:new/delete 与 malloc /free 不能混合使用。 区别点: (1)new /delete 是 C++运算符,而 malloc /free 是标准库函数,用之前要包含其头文件 (2)new 在分配空间时会自动调用类的构造函数,malloc 只管分配空间,不会调用构 造函数 (3)delete 在释放空间时会调用类的析构函数,而 free 则不会调用析构函数 (4)new/delete 是可以重载的,而重载之后,就成为了函数。当 new/delete 在类中被重 载的时候,可以自定义申请过程,比如记录所申请内存的总长度,以及跟踪每个对象的指针。 (5)malloc 在申请内存的时候,必须要提供申请的长度,而且返回的指针是 void*型, 必须要强转成需要的类型。 free 的返回值为空。 (6)new/delete,其实内部也调用了 malloc/free。 注意点: (1)都必须配对使用。 (2)都是申请内存,释放内存。 (3)free 和 delete 可以释放 NULL 指针。 (4)new 若分配堆内存成功则返回指向该内存的空间,若失败则返回 NULL,所以用 new 动态分配内存时,都应该测试 new 的返回指针值,以防分配失败 6. 拷贝构造函数: (1)作用:用已存在的类对象初始化一个正在创建的同类对象。它会自动被调用 (2)以下 3 种情况拷贝构造会被自动调用 ○1 用一个已存在的对象初始化被定义的新对象时 ○2 (3)默认拷贝构造(是一种浅拷贝): 当一个函数的返回值为类的对象时(此时会创建临时对象) ○1 把参数对象的内容按字节拷贝给当前正在创建的对象(逐个成员依次拷贝) ○2 当对象的内存单元有从堆上分配(或其它资源)的时候,应用默认拷贝会造成浅拷贝 7. 浅拷贝与深拷贝 (1)拷贝构造新对象时没有将资源也复制过去(即两个对象同时指向同一资源),称浅拷贝 (2)拷贝构造时将资源同时也复制给新对象,称深拷贝 (3)造成浅拷贝的原因: ○1 类的对象中存在指针类型的数据成员 ○2 (4)当类的数据成员中有指针类型的时候,要自定义拷贝构造,以避免浅拷贝发生 类的默认构造函数采用按字节拷贝方法将一个对象的内容完全复制给另一个对象 8. 临时对象: (1)当函数返回一个对象时,要创建一个临时对象存放到主调函数的内存中 (2)一般的,创建的临时对象在整个创建它们的外部表达式范围内有效,一旦表达式结束, 则临时对象就会被析构 (3)临时对象不能用于引用表达式中(因为引用的实体——临时对象在出了表达式后就被 析构掉了) 9. 无名对象:直接调用构造函数产生无名对象 (1)无名对象的 3 种用法: ○1 可作为实参传递给函数:C++先调用构造函数创建一个无名对象,然后将该无名对象初 始化给了引用形参 ○2 可用来拷贝构造一个新对象:实质上C++将这种情况作了特殊处理:直接定义了一个新 对象,即没有拷贝这一步 ○3 可用来初始化一个引用的声明:等价于定义一个新对象 10. 构造函数用于类型转换,是 C++从类机制中获得的附加性能 (1) 只会尝试含有一个参数的构造函数 (2) 如果有二义性,则放弃尝试 (3) expl icit 限制构造函数用于类型转换:这个关键字是一个声明说明符只能用于在 类的构造函数声明。构造函数声明为 ex plic it 不会被隐式转换的考虑。 11.mutable:加在数据成员声明之前,针对于常成员函数,可以使在其中能改变当前对 象的数据成员 12.常成员函数:在本函数中不能改变本类数据成员的值 第四章 静态成员与友元 1. 静态成员:声明为 static 的类成员能在类范围中共享,称为静态成员 (1)静态数据成员 ○1 静态数据成员不在类中分配空间,其初始化放在类的内部实现的CPP中,初始化时要 用“类名::”引导,其的析构在main() 外,由系统执行,是看不见的。 ○2 静态数据成员的生命周期是全局的,编译器只对它进行一次初始化,其值直到下次改 变为止 ○3 静态数据成员在存储上只需拷贝一次,所有对象都可共享它 ○4 普通成员会随着类对象的创建而创建,但静态成员不会 ○5 (2)静态成员函数 公共静态数据成员可被类的外部访问,保护或私有静态数据成员只可被类的内部访问 ○1 一个静态成员函数不与任何对象相联系,故不能对非静态成员进行默认访问 ○2 类的非静态成员函数可访问所有的数据成员 ○3 静态成员函数没有 this 指针,而非静态成员函数有一个指向当前对象的指针 this 静态成员函数与非静态成员函数的区别: 2. 动态创建对象 对象指针 = new 类名(初始值列表) 动态创建的对象使用完毕后,应使用 delete 将其删除,以释放所占的“堆”内存,释放 时自动调用析构函数析构堆对象 3. 友元:为了提高效率和方便编程 (1)在类里声明一个普通函数时,标上 friend ,则就成了该类的友元,可以访问该类的 一切成员 (2)友元不是类的成员函数,在类的内部只能声明它的函数原型(friend),它的定义则和 类的内部实现放在一块儿 (3)一个类的成员函数可以是另一个类的友元 (4)有友元时,一般要在类的定义前对其进行声明(一般在其声明前也要有类的前向声明) (5)整个类可以是另一个类的友元,该友元称为友类,友类的每个成员函数都可访问另一 个类的任何数据成员 (6)友元关系不能传递,是单向的,也不能被继承,但破坏了类的封装 4. C 和 C++中 static 用法 (1)C 中: ○1 当一个变量被定义成static型时,表明该变量是一个静态变量,存储在静态存储区中, 只能被定义初始化一次;特别的当全局变量被定义成static型时,还表明该变量不能被外部 文件所引用 ○2 (2)C++的类中: 当一个函数被声明为static型时,表明该函数是一个静态函数,不能被外部文件所调用 ○1 当类的数据成员被声明为static型时,表明该成员是一个能被所有对象共享的数据成员, 不与任何具体对象挂勾 ○2 当类的成员函数被声明为static型时,表明该成员 第五章 继承与多态 1. 继承与派生的目的: (1)实现代码的重用 (2)使已存在的类不需修改地适应新应用 2. 继承的特点: (1)每个派生类代表基类的特定版本 (2)基类的属性和方法,派生类必须拥有(构造与析构不会被继承) 3. 继承的 3 种方式:public, private, protected 4. 基类成员在派生类中的访问权限决定之因: (1)成员在基类中的访问权限 (2)继承方式,不同的继承方式的影响(大变小,小不变): ○1 继承方式 基类成员在基类中访问权限 基类成员在派生类中的访问权限 派生类成员对基类成员的访问权限 =========================================================== public public public protected protected private 不能访问 =========================================================== protected public protected protected protected private 不能访问 =========================================================== private public private protected private private 不能访问 ○2 Publ ic: 派生类的对象只能访问基类的 public 成员 派生类对象对基类成员的访问权限 Protected: 派生类的对象不能访问基类的任何成员 Private: 派生类的对象不能访问基类的任何成员 5. 派生类的内存布局: 继承时,在派生类的数据成员中自动生成一个隐藏的基类对象(基类的数据成员) 6. 派生类对象的构造流程:在执行其构造时,先构造基类部分,再构造继承部分 7. 对于多重继承,其构造函数的调用次序: (1) 调用基类,按被继承时的顺序(从左到右) (2) 成员对象的构造函数(按在类中的声明顺序) (3) 派生类的构造函数的函数体中的内容 8 . 派生类的析构函数以构造函数相反的顺序被调用 9. 组合:一个类的数据成员是另一个类的对象(即类中有内嵌对象),称为组合 通常把包含内嵌对象的类称为容器类 (1) 当创建容器类对象时,也同时创建所有内嵌对象 (2) 创建容器类对象时,容器类的构造函数首先被调用,在其执行之前,先自动调 用内嵌对象的构造函数初始化内嵌对象(按声明顺序先后调用),当所有的内 嵌对象的构造函数执行完毕后才开始执行容器类对象的构造函数的函数体。 10.函数的重载、覆盖、隐藏: (1) 重载:成员函数具有以下特征时发生“重载” ○1 在同一个类中 ○2 函数名相同 ○3 参数的类型、个数顺序不同(不能进行隐式转换) ○4 virtual可有可无 (2) 覆盖:指子类函数覆盖父类函数,其特征是: ○5 与函数的返回类型无关 ○1 不在同一个类中(分别位于子类与父类中) ○2 函数名相同 ○3 父类函数必须有virtua l ○4 参数相同 (3) 隐藏:子类函数屏蔽了父类的函数,规则如下: ○5 返回值类型也相同 ○1 如果子类函数与父类函数同名,但返回值或参数不同,此时不论父类函数有没 有virtual,子类函数都将隐藏父类函数 ○2 如果子类函数与父类函数同名,返回值和参数相同,父类函数没有v irtual,则 父 类函数将被隐藏 11. 多态:是指发出同样的消息被不同类型的对象接收后导致完全不同的行为 (1)多态的条件: ○1 有两个是父子关系的类 ○2 有同名的虚函数 ○3 (2)多态的实现: 有父类指针或引用调用子类对象 函数的重载 运算符重载 虚函数 12.虚函数表: (1) 一个类只有一个虚函数表(不管有多少个虚函数,虚函数表只占 4 个存储字节,因 为存储的是指向表的指针) (2) 工作原理:由一个类的所有虚函数地址构成的表就叫虚函数表,当派生类的一个虚 函数覆盖了基类的一个虚函数,则在虚表中用派生类函数的地址替换掉基类函数 的地址。当编译发生动态联编时,从虚表开始查找配对函数,从而确定该调用的 函数并执行调用 (3) 虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的 偏移量)。虚函数表也有结束标志(这个结束标志的值在不同的编译器下是不同 的。在 WinXP+VS2003 下,这个值是 NULL。而在 Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3 下,这个值是如果 1,表示还有下一个虚函数表,如果是 0,表示是最后一个 虚函数表。) (4) 单继承(有覆盖): ○1 覆盖的派生类函数被放到了虚表中原来父类虚函数的位置。 ○2 (5) 多重继承(有覆盖): 没有被覆盖的函数依旧。 ○1 每个父类都有自己的虚表。 ○2 子类的覆盖函数地址会将所有基类的被覆盖函数换上它们的地址。子类的其它没有发 生覆盖的函数被放到了第一个父类的表中。(第一个父类是按照声明顺序来判断的)这样做 就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。 13. C++支持的多态: (1)重载多态 (2)包含多态 (3)强制多态 (4)参数多态(函数模版,类模版) 14.对虚函数的限制: (1)只有类的成员函数才能说明为 virtual 型(虚函数仅适用于有继承关系的类对象) (2)静态成员函数不能是虚函数(静态成员函数不受限于某个对象) (3)内联函数不能是虚函数(内联函数在运行时不能动态确定其位置,即使虚函数在类的 内部定义,编译时,也将其看作是非内联的) (4)构造函数不能是虚函数 (5)析构函数可以是虚函数,而且通常应声明为虚函数(析构函数可构成特殊的多态) 15.抽象类:至少含有一个纯虚函数的类称为抽象类 (1)抽象类不能实例化对象,但可以定义指针,只作为基类出现 (2)构造私有的类也是抽象类 (3)抽象类的派生类只有把基类中所有的纯虚函数全部实例化才能成为具体类,否则 还是抽象类 16. 一个派生类对象在使用上可以被当作一个基类的对象,反之则禁止 (1)派生类对象可被赋值给基类对象 (2)派生类对象可以初始化基类的引用 (3)指向基类的指针也可指向派生类 17.虚基类及派生类构造函数 (1)建立对象时所指定的类称为最(远)派生类 (2)虚基类的成员是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的 (3)在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员 初始化列表中给出对虚基类的构造函数的调用,如未列出,则表示调用该虚基类的默认构造 (4)在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,该派生类的其它基 类对虚基类构造函数的调用被忽略。 第六章 运算符重载 1.目的:使得 C++代码更直观、更易读、 2.运算符重载的本质:函数的调用 3.重载运算符时,要注意该重载运算符的运算顺序与优先级不变 4.运算符是函数,除了运算顺序和优先级不能更改外,参数和返回类型是可以重新说明的, 即可以重载、 5.C++规定,运算符中,参数说明都是内部类型(基本类型)时,不能重载 6.C++规定,“ . :: .* ? sizeof ”不能重载,也不能创造新的运算符 7.当表达式会产生临时变量时,则不能做左值,即不能返回引用,要值返回 当表达式不会产生临时变量时,则可用引用返回 8.增量(++)运算符的重载: (1)前增与后增的区别:前增返回引用,后增则返回值,且以是否有 int 形参为区别标志 (前增没有 int 形参,后增有 int 形参) (2)成员形式重载:只有一个参数(this 代表另一个参数) 非成员形式重载:有两个参数,且是 friend 型的 9.转换运算符(实质是个函数): 如:Operator double() { return jf*100; }//将对象转换为 double 类型 一般将类对象强制转换(通过强制转换运算符),能会调用转换运算符 (1) 优点:有了转换运算符,就不必提供对象参数的重载运算符 (2) 缺点:无法定义其类对象运算符操作的真正含义 (3) 转换运算符与转换构造函数互逆 (4) 转换运算符的重载函数是没有返回类型的,它和类的构造函数,析构函数一样,他 们都没有返回值。 10 .赋值运算符(=)的重载: “=”的重载与其它运算符的重载是类似的,不过,在重载函数中要完成两个功能:一是与 析构类似,取消对象已占用的资源;二是与拷贝构造类似,在其中分配新的资源 如: Name & operator =( Name &s) { Delete [ ]name; CopyName(s.name); Return *this; } (1)在类对象还未存在的情况下,赋值过程是通过拷贝构造函数进行构造处理(Internet b = a; 就是这种情况),但当对象已经存在,那么赋值过程就是通过赋值运算符重载函数处理 (Internet b; b = c;就属于此种情况)。 (2)C++也提供默认的“=”重载,但当对象有堆内存时,会造成浅拷贝 第七章 模板 1. 模板可使程序员能够快速建立具有类似安全的类库集合和函数集合,它的实现,方便了 更大规模的软件开发,模板可以让程序对任何其它数据类型进行同样方式的处理 2. 模板分为类模板,函数模板,它不占空间,其特性是: 类型模板化(泛型化) 3. 函数模板定义形式: Template<类型形式参数表> 返回类型 functionname (形式参数) {//函数体;} 4. 函数模板与模板函数的区别: 函数模板是模板的定义,定义中用到通用类型参数 模板函数是实实在在的函数定义,它由编译系统在碰见具体的函数调用时所生成,具有 程序代码(是函数模板的实例化) 当调用结束后,模板函数就不存在了 5. 类模板定义形式: Template <类型形式参数表(class T)> class className {// 类声明体;} Template <类型形式参数表(class T)> 返回类型 className::memberfunctionname(形式参数表(T)) {// 成员函数定义体;} 创建类模板实例: ClassName<类型实在参数表> object; 对于类模板,类的声明与定义实现部分必须在同一个文件中 6.类模板与模板类的区别: 类模板是模板的定义,不是一个实在的类,定义中用到通用类型参数 模板类是实在的类定义,是类模板的实例化,类定义中参数被实际参数所代替
还剩10页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

wangyunfeibaby

贡献于2012-05-24

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf