目录
一、C++ 语言简介
二、面向对象的基本概念
三、类和对象进阶
四、运算符重载
五、类的继承与派生
六、多态与虚函数
七、输入/输出流
八、文件操作
九、函数模板与类模板
一、C++ 语言简介
知识点名称 | 内容 | ||
C++语言的 发展简史 ★★ | 1. C 语言是 C++ 语言的前身 ,在进一步扩充和完善 C 语言的基础上得到了 C++ 语言。 2. 用 C++ 语言写成的程序称为源程序,源程序必须经过 C++ 编译程序翻译成机器语言才能执行。 (1)一般需要经过编辑、编译、连接、运行。 3. C++ 语言的主要特点表现在两个方面: (1)它是 C 语言的继承,尽量兼容 C 语言,既保持了 C 语言的简洁和高效,可以像 C 语言那样进行结构化程序设计,同时也增强了 C 语言对类型的处理。 (2)加入了面向对象的特征。 | ||
C++语言的 特点 ★★ | 1. 与 C 语言相比 ,C++ 语言的优点: (1)从程序运行的稳定性来说,C++ 语言更安全, 它支持过程化编程、面向对象编程和泛型编程。 (2)C++ 语言可运行于多种平台上,如 Windows 、MAC 操作系统及 UNIX 的多种版本。 (3)C++ 语言中加入了面向对象的概念,C++ 的程序结构与 C 语言的程序结构存在很大差别。 | ||
基本的 输入/输出 ★★★★★ | 1. C++ 类中对象: (1)cin :运算符为 >> ,用于键盘输入。函数 scanf();输入流类 istream (2)cout :运算符为 << ,用于屏幕输出。函数 printf();输出流类 ostream 2. 流提取运算符和流插入运算符都是由两个连续的符号组成的,中间不能有其他符号 。 3. %c 是输出单个字符的格式控制符。%s 是输出字符串的格式控制符。 4. 当使用当程序中用到 cin 和 cout 时,需要在程序中包含头文件 <iostream> 。 5. 语句以分号“ ; ”结尾。 | ||
头文件和 命名空间 ★★★★★ | 1. 常用的头文件有以下一些: (1)标准输入输出流: <iostream> 。 (2)标准文件流: <fstream> 。 (3)标准字符串处理函数: <string> 。 (4)标准数学函数: <cmath>。 程序员还可以定义自己的头文件,并在程序中使用 #include 指令将其包含进来。 通常,使用尖括号括住系统提供的头文件,使用双引号括住程序员自己定义的头文件。 2. using 语句引用其他命名空间的标识符的语法格式有两种形式: (1)using 命名空间名::标识符; (2)using namespace 命名空间名; | ||
强制类型 转换运算符 ★★ | 1. 数据类型级别由低到高分别为:char→int→float→double。 (1)当不同类型的量进行混合算术运算时,系统自动进行合理的类型转换。 (2)编译器就会自动把低级类型向高级类型转换。 2. 使用强制类型转换运算符 static__cast 或是 const__cast 进行转换。 (1)static__cast 将一种数据类型转换成另一种数据类型,格式:static__cast<类型名>(表达式) static__cast 也可以省略。 (2)const__cast 去除指针和引用的常量性,但不能去除变量的常量性:const__cast<类型名>(表达式) | ||
函数参数的 默认值 ★★★★★ | 1. C++ 语言规定,提供默认值时必须按从右至左的顺序提供,即有默认值的形参必须在形参列表的最后。 (1)如果有某个形参没有默认值,则它左侧的所有形参都不能有默认值。 2. 调用函数时,主调函数的实参与被调函数的形参按从左至右的顺序进行匹配对应。 (1)如果实参的个数与形参的个数相等,则它们一一对应 。 (2)如果实参的个数 m 少于形参的个数 n ,则函数原型形参表中最前面的 m 个形参与 m 个实参相对应,后面的 n-m 个形参则使用默认值进行初始化。 3. 无返回值函数 :没有返回值的 return 语句只能用在返回类型是 void 的函数中。 (1)有返回值函数:return 语句的第二种形式提供了函数的结果。 (2)只要函数的返回类型不是 void,则该函数内的每条 return 语句必须返回一个值。 | ||
引用和函数 参数的传递 ★★★★★ | 1. 引用相当于给变量起了一个别名。定义格式:类型名 &引用名=同类型的某变量名; 2. 在 C++ 中, 函数调用时参数的传递有两种方式:传值和传引用。 (1)传值:实际上是传递对象的值。 即将实参的值拷贝给形参。 在函数执行过程中,都是对这个拷贝进行操作的,函数执行完毕返回后,形参的值并不拷贝回实参,也就是说函数内部对形参的改变不会影响到函数外实参的值。 (2)传引用:传递对象的首地址值。 函数调用时,实参对象名传递给形参对象名,形参对象名就成为实参对象名的别名,即形参是对应实参的引用,它们是等价的,代表同一个对象,也可以看作是将实参的地址传递给了形参 。 | ||
const 与指 针共同使用 ★★★★ | 1. C++ 语言也可以使用 const 限定访问权限,const 修饰指针变量时,基本含义如下: (1)如果唯一的 const 位于符号 * 的左侧,表示指针所指数据是常量,数据不能通过本指针改变,但可以通过其他方式进行修改;指针本身是变量,可以指向其他的内存单元。 (2)如果唯一的 const 位于符号 * 的右侧,表示指针本身是常量,不能让该指针指向其他内存地址;指针所指的数据可以通过本指针进行修改。 (3)在符号 * 的左右各有一个 const 时,表示指针和指针所指数据都是常量,既不能让指针指向其他地址,也不能通过指针修改所指向的内容。 【助记 :可以简单地记住 const 的修饰规则:const 修饰其左侧的内容;如果 const 是本行的第一个标识符 ,则它修饰其右侧的内容 。 】 | ||
内联函数 ★★★★ | 1. 引入了内联函数的目的:加快执行速度。 (1)定义内联函数时只需在函数头返回值类型的前面加上关键字 inline 。 2. 内联函数的适用情况:只有几条语句,且频繁调用的小函数。 3. 在 C++ 中,除具有循环语句、switch 语句的函数不能说明为内联函数外,其他函数都可以说明为内联函数 。 | ||
函数的重载 ★★★★ | 1. 函数重载:是指在程序的同一范围内声明几个功能类似的同名函数。 (1)即前提是函数名相同。 (2)可提高代码可读性。 (3)函数重载可使一个函数名具有多种功能,即具有“多种形态 ”,称这种特性为多态性。 2. 实现函数的重载必须满足下列条件之一: (1)参数表中对应的参数类型不同。 (2)参数表中参数个数不同。 | ||
指针和动态 内存分配 ★★★★ | 1. 指针变量中保存的是一个地址 ,有时也称指针指向一个地址。 2. 使用 new 运算符动态申请的内存空间,需要在使用完毕释放。C++ 提供了 delete 运算符,用来释放动态分配的内存空间。 (1)使用 new 运算符实现动态内存分配。p=new T; 其中,T 是任意类型名,p 是类型为 T* 的指针。 (2)使用 new 运算符还可以动态分配一个任意大小的数组:p=new T[N]; 其中,T 是任意类型名,p 是类型为 T*的指针, N 代表数组“元素个数 ”,可以是任何的值为正整数的表达式。 (3)C++ 提供了 delete 运算符,用来释放动态分配的内存空间,基本用法:delete 指针 3. 当 delete 释放动态对象数组时,实现为 delete []ptr; 4. 数组的下标从 0 开始,含 n 个元素的数组的下标范围是从 0〜n-1 。 | ||
用 string 对象 处理字符串 ★★★★★ | 1. 字符常量:用单引号括起来的单个字符或转义字符。 (1)字符串常量:用双引号括起来。 2. 大小写字母 ASCII 码差 32 。 3. string 类中的常用成员函数: (1)int size() const; 返回当前字符串的大小 (2)int length() const; 返回当前字符串的长度 (3)bool empty() const; 判定当前字符串是否为空 (4)find(); 返回 str 在字符串中第一次出现的位置 ,如果没找到则返回-1 (5)insert(); 在 p 位置插入字符串 S (6)append(); 将字符串 s 连接到当前字符串的结尾处 (7)substr(); 返回从 pos 开始的 n 个字符组成的字符串 | ||
C++语言的 程序结构 ★★★ | 1. 程序中必须有且仅有一个主函数 main() ,这是程序执行的总入口。 2. C++ 程序中,仍沿用 C 语言的注释风格,即注释有以下两种形式。 (1)从 /* 开始 ,到 */ 结束,这之间的所有内容都视作注释 。 (2)从 // 直到行尾,都是注释。 |
二、面向对象的基本概念
知识点名称 | 内容 | ||
结构化 程序设计 ★ | 1. 在编写程序时,使用 3 种基本控制结构来构造程序:顺序、选择、循环基本控制结构。 | ||
面向对象 思想的提出 ★★★★ | 1. 对象是类的一个实例。 (1)对象是类的一个具象,类是对象的一个抽象。 2. 面向对象技术把问题看成是相互作用的事物的集合,也就是对象的集合。 3. 对象特性:一是状态(也称为属性);二是行为(也称为操作)。 (1)状态是指对象本身的信息,也称为属性;行为是对对象的操作。 4. 通过对事物的抽象找出同一类对象的共同属性(静态特征)和行为(动态特征) ,从而得到类的概念 。 5. (1)在结构化程序设计中,采用自顶向下、逐步求精及模块化的思想,将复杂的大问题层层分解为许多简单的小问题。 (2)面向对象的程序设计方式更接近于人们看待真实世界的情况。真实世界是由各类不同的事物组成的。 | ||
面向对象 程序设计 的特点 ★★★★ | 1. 抽象:在面向对象的程序设计方法中,将同一类事物的共同特点概括出来。 (1)对象的特点包括两个方面:属性和操作。 (2)C++ 中使用对象名、属性和操作三要素来描述对象。 2. 封装:将对象的属性及实现细节隐藏起来,只给出如何使用的信息。 (1)将数据成员使用 private 关键字定义,则产生封装性。 3. 继承就是在编写一个“新”类的时候,以现有的类作为基础,使得新类从现有类“派生 ”而来,从而达到代码扩充和代码复用的目的。 (1)原来的类是基类,也称为父类或超类。 (2)新类是派生类,也称为子类。 4. 多态是指不同种类的对象都具有名称相同的行为,而具体行为的实现方式却有所不同。 | ||
类的定义 ★★★★★ | 1. 标识符命名规则: (1)字母、数字和下划线的组合,大小写敏感,但不能以数字开头,也不能和系统中使用的关键字完全相同。 2. 面向对象方法中的类,是对具有相同属性和行为的同一类对象的抽象描述,其内部包括属性(本类的成员变量)和行为(本类的成员函数)两个主要部分,即类以数据为中心,把相关的一批函数组成为一体。 3. 类中定义的数据和函数称为这个类的成员(数据成员和成员函数)。 4. 类体外函数定义的前面必须用“类名::”来限定,格式如下: 返回值类型 类名::成员函数名(参数列表) { 成员函数的函数体 } | ||
程序结构 ★★ | 1. .h 文件是头文件 2. .cpp 文件是源程序文件 3. C 源程序文件编译而成的目标文件的扩展名是 .obj 4. 可执行代码的文件扩展名为 .exe | ||
创建类对象 的基本形式 ★★★ | 1. 使用“类名 *对象指针名 = new 类名;”创建对象时,调用无参的构造函数。 (1)如果这个构造函数是由编译器为类提供的,则类中成员变量不进行初始化。 2. 使用“类名 *对象指针名 = new 类名();”创建对象时,也调用无参的构造函数。 (1)如果这个构造函数是由编译器为类提供的,则对类中的成员变量进行初始化。 | ||
访问对象的 成员 ★★★★ | 1. 使用对象:如果变量 a 为结构体对象,且结构体内有元素 b,那么可以使用 a.b 的方式访问元素。 2. 使用指针:如果变量 a 为结构体指针,且结构体内有元素 b,那么可以使用 a->b 的方式访问元素。 3. 使用引用:访问成员时仍使用点操作符,即“引用名.成员名”。 | ||
访问范围说 明符的含义 ★★★★★ | 1. private 私有的:使用它修饰的类的成员仅能在本类内被访问。(默认) 2. public 公有的:使用它修饰的类的成员可以在程序的任何地方被访问。 3. protected 保护的:它的作用介于 public 与 private 之间,使用它修饰的类的成员能在本类内及子类中被访问。 | ||
标识符的 作用域与 可见性 ★★ | 1. 函数原型作用域:在声明函数原型时形参的作用范围就是函数原型作用域,最小的作用域。 2. 局部作用域:程序中使用相匹配的一对大括号括起来的一段程序称为块。 (1)作用域局限在块内的称为局部作用域。 3. 类作用域:类可以被看成是一组有名字的成员的集合,类 X 的成员 m 具有类作用域,对 m 的访问方式有如下 3 种: (1)直接访问成员 m。 (2)在类外,通过表达式 x.m 或者 X::m 来访问 (3)在类外,可以通过 ptr->m 表达式来访问。 4. 命名空间作用域:在命名空间内部可以直接引用当前命名空间中声明的标识符,如果需要引用其他命名空间的标识符,需要使用下面的方式:命名空间名::标识符名 |
三、类和对象进阶
知识点名称 | 内容 | ||
构造函数的 作用 ★★★★ | 1. 对于 C++ 中基本数据类型的变量,可以声明全局变量和函数内部的局部变量。 (1)全局变量:如果没有进行初始化,则系统自动为其初始化为 0。这个工作在程序启动时完成。 (2)局部变量:系统不进行自动初始化,如果程序员没有设定,则是一个随机值。 2. 构造函数的作用:完成对象的初始化工作(即创建对象)。 (1)构造函数是类中的特殊成员函数,它属于类的一部分。 3. 声明对象后,可以使用 new 运算符为对象进行初始化,此时调用的是对象所属类的构造函数。 | ||
构造函数的 定义 ★★★★★ | 1. 构造函数的函数名与类名相同,没有返回值。 (1)一个类的构造函数可以有多个,即构造函数允许重载。 (2)即这些构造函数之间的关系是重载关系。 2. 当类中没有定义任何构造函数时,系统会自动添加一个参数表为空、函数体也为空的构造函数,称为默认构造函数。 3. 定义构造函数的形式: 类名::类名(形参 1,形参 2,…,形参 n) { x1=形参 1; x2=形参 2; …… xn=形参 n; } | ||
构造函数的 使用 ★★★ | 1. 如果程序中声明了对象数组,即数组的每个元素都是一个对象。 2. 创建对象时,调用一次构造函数。 3. 对于指针,仅是说明了这个指针,并未与对象相关,所以并不调用构造函数。 4. 如果构造函数的定义中给出了参数的默认值,那么使用构造函数创建对象时,对应的实参是可以省略的。 (1)此时,使用默认值当作对应实参的值。 | ||
复制 构造函数 ★★★★ | 1. 复制构造函数是构造函数的一种,也称为拷贝构造函数。 (1)它的作用是使用一个已存在的对象去初始化另一个正在创建的对象。 2. 复制构造函数只有一个参数,参数类型是本类的引用。 (1)即引用类自己。 3. 对于类 A 而言,复制构造函数的原型如下: (1)格式一:A::A(const A&) (2)格式二:A::A(A &) | ||
析构函数 ★★★★★ | 1. 与构造函数一样,析构函数也是成员函数的一种,它的名字也与类名相同,但要在类名前面加一个“〜”字符,以区别于构造函数。 2. 析构函数的特点:没有参数,也没有返回值。 (1)析构函数不可以多于一个,不会有重载的析构函数。 (2)默认析构函数的函数体为空。 (3)一个类中有且仅有一个析构函数。 3. 创建对象时自动调用构造函数,在对象消亡时自动调用析构函数。 | ||
静态变量 ★★★★ | 1. static 用来声明静态变量。 2. 局部变量:块内定义的变量,从定义之处开始到本块结束处为止是局部变量的作用域。 3. 全局变量:指在所有花括号之外声明的变量,其作用域范围是全局可见的,即在整个项目文件内都有效。 | ||
类的 静态成员 ★★★ | 1. 类的静态成员有两种:静态成员变量和静态成员函数。 2. 给静态成员变量赋初值的格式:类型 类名::静态成员变量=初值; 3. 访问类静态成员格式: (1)类名::静态成员名 (2)对象名.静态成员名 (3)对象指针->静态成员名 4. 静态成员变量只有一份,被同类所有对象共享。 (1)甚至可以在还没有任何对象生成时就访问一个类的静态成员。 | ||
常量成员和 常引用成员 ★ | 1. 使用关键字 const 修饰的量称为常量。 2. 在对象被创建以后,其常量成员变量的值就不允许被修改,只可以读取其值。 (1)对于常量对象,只能调用常量函数。 (2)总之,常量成员变量的值不能修改,常量对象中的各个属性值均不能修改。 | ||
友元 ★ | 1. 友元使用关键字 friend 标识。 2. 友元的概念破坏了类的封装性和信息隐藏,但有助于数据共享,能够提高程序执行的效率。 | ||
友元函数 ★★★★★ | 1. 在友元函数内部可以直接访问本类对象的私有成员。 2. 在类定义中,将一个全局函数声明为本类友元函数:friend 返回值类型 函数名(参数表); (1)当有某类 A 的定义后,将类 A 的成员函数说明为本类的友元函数:friend 返回值类型 类 A::类 A 的成员 函数名(参数表); 3. 一个类的成员函数(包括构造函数和析构函数)可以通过使用 friend 说明为另一个类的友元,但友元函数本身并不是类的成员函数,但允许访问类中的所有成员。 | ||
友元类 ★★★★ | 1. 在类定义中声明友元类的格式如下:friend class 类名; 2. 友元类的关系是单向的。 (1)若说明类 B 是类 A 的友元类,不等于类 A 也是类 B 的友元类。 (2)友元类的关系不能传递,即若类 B 是类 A 的友元类,而类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。 3. 友元函数不是类的成员函数,但允许访问类中的所有成员。 (1)在函数体中访问对象成员时,必须使用“对象名.对象成员名”的方式。 (2)在主函数中,调用全局有元函数时,直接写函数名即可。 | ||
this 指针 ★★★ | 1. C++ 语言规定,当调用一个成员函数时,系统自动向它传递一个隐含的参数。 (1)该参数是一个指向调用该函数的对象的指针,称为 this 指针,从而使成员函数知道对哪个对象进行操作。 2. 目的:使用 this 指针,保证了每个对象可以拥有自己的数据成员,但处理这些数据成员的代码可以被所有的对象共享。 3. 在非静态成员函数内部可以直接使用 this 关键字,this 就代表指向该函数所作用的对象的指针。 |
四、运算符重载
知识点名称 | 内容 | ||
重载运算符 的概念 ★★★★★ | 1. 可重载的运算符: (1)双目算术运算符 +(加),-(减),*(乘),/(除),%(取模) (2)关系运算符 ==(等于),!=(不等于),<(小于),>(大于),<=(小于等于),>=(大于等于) (3)逻辑运算符 ||(逻辑或),&&(逻辑与),!(逻辑非) (4)单目运算符 +(正),-(负),*(指针),&(取地址) (5)自增自减运算符 ++(自增),--(自减) (6)…… 2. 不可重载的运算符: (1)成员访问运算符 . (2)成员指针访问运算符 .*,->* (3)域运算符 :: (4)长度运算符 sizeof (5)条件运算符 ?: (6)预处理符号 # 3. 运算符函数的格式如下: 返回值类型 operator 运算符(形参表) { 函数体 } 4. 重载运算符的使用 (1)如果定义为全局函数,对于二元运算符,需要为函数传递两个参数。 (2)如果定义为类的成员函数,对于二元运算符,则只需要传递一个参数。 | ||
重载运算符 的规则 ★★★ | 1. 重载后运算符的含义应该符合原有的用法习惯。 2. 运算符重载不能改变运算符原有的语义,包括运算符的优先级和结合性。 3. 运算符重载不能改变运算符操作数的个数及语法结构。 4. 不能创建新的运算符,即重载运算符不能超出 C++语言允许重载的运算符范围。 5. 重载运算符“()”“[]”“->”或者赋值运算符“=”时,只能将它们重载为成员函数,不能重载为全局函数。 6. 运算符重载不能改变该运算符用于基本数据类型对象的含义。 | ||
重载流插入 运算符和流 提取运算符 ★ | 1. 重载流插入运算符的一般格式如下: ostream &operator<<(ostream & output, 类名&对象名) { …… return output; } | ||
重载自增、 自减运算符 ★★★★ | 1. 自增运算符“++”有前置和后置之分。 (1)例如,obj 是一个类 CDemo 的对象,“++obj”的返回值应该是 obj 被修改后的值,而“obj++”的返回值应该是 obj 被修改前的值。 2. 使用类运算符“++”运算符,使用函数调用方式。 (1)例:若前缀:++n 为 n.operator++(); (2)例:若后缀:n++为 n.operator++(0); |
五、类的继承与派生
知识点名称 | 内容 | ||
继承的概念 ★★★ | 1. 使用基类派生新类时,除构造函数和析构函数外,基类的所有成员自动成为派生类的成员,包括基类的成员变量和成员函数。 2. 派生类可以重新定义或修改基类中已有的成员,包括可以改变基类中成员的访问权限。 (1)当然派生类需要定义自己的构造函数和析构函数。 3. 派生类的成员覆盖基类的同名成员。 (1)覆盖也称为重定义或是重写。 (2)对于成员函数来说,派生类既继承了基类的同名成员函数,又在派生类中重写了这个成员函数。 (3)这称为函数重定义,也称为同名隐藏。 | ||
派生类 的定义 ★★★★★ | 1. 在 C++ 语言中,从基类派生派生类的一般格式如下: class 派生类名: 继承方式说明符 基类名 { 类体 }; | ||
继承关系 的特殊性 ★★ | 1. 基类的友元不一定是派生类的友元;基类的成员函数是某类的友元函数,则其作为派生类继承的成员函数仍是某类的友元函数。 2. 如果基类的静态成员是公有的或是保护的,则它们被其派生类继承为派生类的静态成员。 (1)访问这些成员时,通常用“<类名>::<成员名>”的方式引用或调用。 3. 除基类的构造函数和析构函数外,派生类可以继承基类的全部成员变量和成员函数。 | ||
多重继承 ★★ | 1. C++ 中有两种继承:单一继承和多重继承。 (1)对于单一继承,派生类只能有一个基类; (2)对于多重继承,派生类可以有多个基类,指一个派生类同时有一个以上的基类,多个基类中的所有成员除构造函数和析构函数外都被派生类继承。 | ||
访问控制 ★★★★ | 1. 继承方式不同,基类中的成员在派生类中的访问权限可能也不同。
(3)保护继承中,基类的公有成员以保护成员的身份出现在派生类中,而基类的私有成员不可以直接访问。
| ||
构造函数与 析构函数 ★★★★★ | 1. 派生类构造函数必须对这三类成员进行初始化,其执行顺序: (1)调用基类构造函数; (2)调用子对象的构造函数; (3)派生类的构造函数体。 2. 在执行一个派生类的构造函数之前,总是先执行基类的构造函数。 (1)派生类对象消亡时,先执行派生类的析构函数,再执行基类的析构函数。 | ||
类与类之间 的关系 ★ | 1. 继承关系也称为“is a”关系或“是”关系。 2. 组合关系也称为“has a”关系或“有”关系,表现为封闭类,即一个类以另一个类的对象作为成员变量。 3. 继承可以是多级的,类 A 可以是类 B 的基类,类 B 可以是类 C 的基类。 (1)可以说类 C 的对象是类 B 中的一员,也是类 A 中的一员。 (2)即“is a”关系具有传递性。 | ||
多层次的 派生 ★ | 1. 在 C++ 中,派生可以是多层次的。 (1)如类 A 派生类 B,类 B 可以再派生类 C,类 C 又能够派生类D,以此类推。 (2)在 C++中,类之间的继承关系具有传递性。 |
六、多态与虚函数
知识点名称 | 内容 | ||
多态 ★★★ | 1. 多态分为: (1)编译时多态:静态绑定/早绑定,主要是指函数的重载(包括运算符的重载)。 (2)运行时多态:动态绑定/晚绑定,和继承、虚函数等概念有关。 2. 不论是静态还是动态,多态性肯定是调用同名的函数。 3. 在类之间满足赋值兼容的前提下,实现动态绑定必须满足以下两个条件。 (1)必须声明虚函数。 (2)通过基类类型的引用或者指针调用虚函数。 4. 在面向对象的程序设计中,使用多态能够增强程序的可扩充性。 (1)此外,使用多态也能起到精简代码的作用。 | ||
虚函数 ★★★★ | 1. 所谓“虚函数”,就是在函数声明时前面加了 virtual 关键字的成员函数。 2. 声明虚函数成员的一般格式:virtual 函数返回值类型 函数名(形参表); 3. 通过基类指针或基类引用调用虚函数时,都会产生动态多态。 4. 虚函数的注意事项: (1)虚函数一般不声明为内联函数。 (2)派生类重写基类的虚函数实现多态,要求函数名、参数列表及返回值类型要完全相同。 (3)基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。 (4)只有类的非静态成员函数才能定义为虚函数,静态成员函数和友元函数不能定义为虚函数。 (5)如果虚函数的定义是在类体外,则只需在声明函数时添加 virtual 关键字,定义时不加 virtual 关键字。 (6)构造函数不能定义为虚函数。 (7)不要在构造函数和析构函数中调用虚函数。 (8)最好将基类的析构函数声明为虚函数。 | ||
多态的使用 ★ | 1. 因为类的成员函数之间是可以互相调用的,所以在普通成员函数(静态成员函数、构造函数和析构函数除外)中调用其他虚成员函数也是允许的,并且是多态的。 2. 在构造函数和析构函数中可以调用虚函数,但这样调用的虚函数不是多态的。 | ||
虚析构函数 ★★★★ | 1. C++ 允许声明虚析构函数。 (1)声明虚析构函数的一般格式:virtual 〜类名(); (2)虚析构函数没有返回值类型,没有参数。 2. 如果一个类的析构函数是虚函数,则由它派生的所有子类的析构函数也是虚析构函数。 | ||
纯虚函数 ★★★★★ | 1. 纯虚函数:声明在基类中的虚函数,没有具体的定义,而由各派生类根据实际需要给出各自的定义。 2. 声明纯虚函数的一般格式:virtual 函数类型 函数名(参数表)=0; 3. 定义纯虚函数的几个要素是: (1)使用 virtual 关键字进行修饰; (2)函数定义中要有“=0”,且没有函数体,大括号也没有。 | ||
抽象类 ★★★★ | 1. 包含纯虚函数的类称为抽象类。 (1)即抽象类至少含有一个纯虚函数。 2. 抽象类的派生类中,如果没有给出全部纯虚函数的定义,则派生类继续是抽象类。 (1)直到派生类中给出全部纯虚函数定义后,才能实例化一个对象。 (2)虽然不能创建抽象类的对象,但可以定义抽象类的指针和引用。 (3)这样的指针和引用可以指向并访问派生类的成员,这种访问具有多态性。 | ||
虚基类 ★ | 1. 定义虚基类的一般格式: class 派生类名:virtual 派生方式 基类名 { 派生类体 }; |
七、输入/输出流
知识点名称 | 内容 | ||
流类简介 ★★ | 1. C++ 的标准库中有一个面向对象的输入/输出软件包,即 I/O 流类库,输入和输出均是通过流完成的。流是 I/O 流类的核心概念。 (1)输出操作是将一个对象转换成一个字符序列,输出到指定对象。 (2)输入操作是从某个对象接收到一个字符序列,然后将其转换为相应对象所要求的格式。 2. 常见的头文件有以下 3 个: (1)iostream:包含操作所有输入/输出流所需的基本信息。 (2)iomanip:包含格式化 I/O 的带参数流操纵符,可用于指定数据输入/输出的格式。 (3)fstream:包含处理文件的有关信息,提供建立文件、读/写文件的各种操作接口。 | ||
标准流对象 ★★ | 1. C++ 在头文件 iostream 中为用户预定义了 4 个标准流对象,分别是: (1)cin (标准输入流) (2)cout (标准输出流) (3)cerr (非缓冲错误输出流) (4)clog (缓冲错误输出流) 2. 重定向,就是改变默认的输入来源,或改变默认的输出目的地。 (1)重定向函数 freopen 的原型:FILE *freopen( const char *path, const char *mode, FILE *stream); (2)函数 freopen() 的功能:将 stream 按 mode 指定的模式重定向到路径 path 指向的文件。 如果重定向时发生错误,则关闭原来的 stream,函数返回 NULL。 mode 可以是 "w”(写)或 "r”(读)方式。 | ||
流操纵符 ★★★★ | 1. 进制数与前缀 (1)十六进制常量 —— 前缀 0x (2)十进制常量 —— 无前后缀 (3)八进制常量 —— 前缀 0 (4)长整型常量 —— 后缀 L 或 l 2. iostream 中常用流操纵符 (1)endl 输出一个新行符,并清空流 (2)ends 输出字符串结束,并清空流 (3)flush 清空流缓冲区 (4)dec * 以十进制形式输入或输出整数 (5)hex 以十六进制形式输入或输出整数 (6)oct 以八进制形式输入或输出整数 (7)ws 提取空白字符 3. 常用的用于格式控制的流操纵符 (1)setw(),setprecision(),setfill(),setbase(),setiosflags,resetiosflags 等。 (2)在头文件 iomanip 中还定义了一些用于格式控制的流操纵符。 (3)setbase(int b):设置输出整数时的进制,b 为 8、10 或 16。 (4)setfill(int c):在指定输出宽度的情况下,输出的宽度不足时用 ASCII 码为 c 的字符填充(默认情况是用空格填充)。 (5)setprecision(int n):设置输出浮点数的精度为 n。 (6)setw(int w):指定输出宽度为 w 个字符,或输入字符串时读入 w 个字符,一次有效。 | ||
调用 cout 的 成员函数 ★★ | 1. ostream 类提供了在 cout 中控制输出格式的成员函数。常见的用于控制格式的成员函数原型: (1)设置和返回标志字:flags() (2)设置标志位:setf() (3)清除标志位:unsetf() (4)设置和返回输出宽度:width() (5)设置填充字符:fill() (6)设置数据显示精度:precision() 2. ostream 类还有一些输出流的成员函数,其原型如下: (1)字符插入:ostream & put(char c); 成员函数 put() 的功能是向输出流中插入一个字符 c。 如果给出的参数类型为 int,则输出该 ASCII 码对应的字符,函数返回输出流对象的引用。 (2)数据块插入:ostream & write(const char * pch, int nCount); 成员函数 write() 的功能是向输出流中插入 pch 指向的一个长度为 nCount 的字节序列。 | ||
调用 cin 的 成员函数 ★ | 1. istream 类提供了一些公有成员函数,它们可以以不同的方式提取输入流中的数据: (1)get() 函数:此函数从输入流中读入一个字符(包括空白字符),返回值就是该字符的 ASCII 码。 (2)getline() 函数:是从输入流中的当前字符开始读取 bufSize-1 个字符到缓冲区 buf,或读到'\n'为止(哪个条件先满足即按哪个执行)。函数会在 buf 中读入数据的结尾自动添加串结束标记'\0'。 (3)eof() 函数:用于判断输入流是否已经结束。返回值为 true 表示输入结束。 (4)ignore() 函数:作用是跳过输入流中的 n 个字符。 |
八、文件操作
知识点名称 | 内容 | ||
文件的概念 ★ | 1. C++ 根据文件数据的编码方式不同分为文本文件和二进制文件。 2. 根据存取方式不同分为顺序存取文件和随机存取文件。 3. 对文件的基本操作分为读文件和写文件。 (1)所谓“读文件”就是将文件中的数据读入内存之中,也称为“输入”。 (2)所谓“写文件”就是将内存中的数据存入文件之中,也称为“输出”。 | ||
C++ 文件流类 ★★★★ | 1、C++ 标准类库中有 3 个流类可以用于文件操作,这 3 个类统称为文件流类,分别如下: (1)ifstream:用于从文件中读取数据。 (2)ofstream:用于向文件中写入数据。 (3)fstream:既可用于从文件中读取数据,又可用于向文件中写入数据。 2、使用这 3 个流类时,程序中需要包含 fstream 头文件。 3、使用文件的基本步骤: 打开(open)文件 —— 操作文件 —— 关闭(close)文件。 | ||
打开文件 ★★★★ | 1. 打开文件的目的: (1)建立关联。通过指定文件名,建立起文件和文件流对象的关联。 (2)指明文件的使用方式和文件格式。 2. 打开文件的方式: (1)先建立流对象,然后调用 open()函数连接外部文件。格式: 流类名 对象名; 对象名.open(文件名,模式); (2)调用流类带参数的构造函数,在建立流对象的同时连接外部文件。格式如下: 流类名 对象名(文件名,模式); ① 模式: Ⅰ. ios::in :以读方式打开文件。 Ⅱ. ios::out :以写方式打开文件。 Ⅲ. ios::in | ios::out:既可读取其内容,也可向其写入数据。 Ⅳ. ios::app:以追加方式打开文件,用于在文件尾部添加数据。 ② 文件名: Ⅰ. 可以是已经赋值的字符串,也可以是字符串常量。 Ⅱ. 可以是包含完整路径的绝对文件名,也可以是只包含相对路径的文件名。 Ⅲ. 其中“\\”是 C++ 的转义字符,代表路径中的一个“\”。 Ⅳ. 故打开文件 "d:\file.dat" 的表示方式为:"d:\\file.dat"。 | ||
关闭文件 ★ | 使用 fstream 中的成员函数 close() 关闭文件。 | ||
读写二进制 文件 ★ | 1. 用 ostream::write() 成员函数写文件 2. 用 istream::read() 成员函数读文件 3. 用 ostream::gcount() 成员函数得到读取字节数 | ||
用成员函数 put()和 get() 读写文件 ★★ | 1. 读写文本文件: (1)成员函数 put() 向文件中一次写入一个字节。 (2)成员函数 get() 从文件中一次读取一个字节。 2. 函数 get() 有 3 种主要形式: (1)intget(); —— 不带参数的 get()函数从指定的输入流中提取一个字符(包含空白字符),函数的返回值即为该字符。 (2)istream& get(char &rch); —— 从指定输入流中提取一个字符(包含空白字符),将该字符作为rch 引用的对象。 (3)istream& get(char *pch, int nCount, char delim='\n'); —— 从流的当前字符 开始 , 读取 nCount-1 个字符,或遇到指定的分隔符 delim 结束。 | ||
随机访问 文件 ★ | 1. 成员函数 seekg(),可以设置文件读指针的位置。 2. 成员函数 seekp(),可以设置文件的写指针位置。 |
九、函数模板与类模板
知识点名称 | 内容 | ||
函数模板 的 概念 ★★★★★ | 1. 定义 (1)函数模板:函数在设计时并不使用实际的类型,而是使用虚拟的类型参数。 ① 这样可以不必为每种不同的类型都编写代码段。当用实际的类型来实例化这种函数时,将函数模板与某个具体数据类型连用。 ② 即这个通用函数就是函数模板。 (2)模板函数:编译器将以函数模板为样板,生成一个函数,即产生了模板函数,这个过程称为函数模板实例化。 ① 模板函数的真正代码是在源程序中调用函数时产生。 2. 定义函数模板的一般格式如下: template <模板参数表> 返回类型名 函数模板名(参数表) { 函数体的定义 } (1)模板参数表:由用逗号分隔的模板参数构成,形式是“类型 参数名,类型 参数名,……”。 ① 如果是一个类型,则需要使用 typename 或 class 关键字来表示参数的类型,一般选用 T 作为标识符来 标识类型参数。 | ||
函数模板 的 示例 ★★ | 1. 调用函数模板时,不进行实参到形参类型的自动转换。 (1)同一个类型参数只能替换为同一种类型。 (2)应保持参数类型一致。 2. 函数模板与函数的区别: (1)函数模板本身在编译时不会生成任何目标代码,只有当通过模板生成具体的函数实例时才会生成目标代码。 (2)被多个源文件引用的函数模板,应当连同函数体一同放在头文件中,而不能像普通函数那样只将声明放在头文件中。 (3)函数指针也只能指向模板的实例,而不能指向模板本身。 | ||
函数或 函数模板 调用语句的 匹配顺序 ★★★★★ | 1. 在函数和函数模板名字相同的情况下,C++ 编译器遵循以下先后顺序: (1)先找参数完全匹配的普通函数(不是由模板实例化得到的模板函数)。 (2)再找参数完全匹配的模板函数。 (3)然后找实参经过自动类型转换后能够匹配的普通函数。 (4)如果上面的都找不到,则报错。 | ||
类模板 概念 ★★★★★ | 1. 定义 (1)使用类模板,用户可以为类定义一种模式,使得类中的某些成员变量、默认成员函数的参数、某些成员函数的返回值及局部变量能取任意类型,既可以是系统预定义的类型,也可以是用户自定义的类型。 ① 通过类模板,可以实例化一个个的类。 (2)由类模板实例化得到的类称为模板类。 (3)关系:编译器由类模板生成类的过程称为类模板的实例化。 ① 由类模板实例化得到的类称为模板类。 2. 类模板声明的格式:template<模板参数表> class 类模板名{ //类体定义}; 3. 用类模板定义对象的一般格式: (1)类模板名 <模板参数表> 对象名 1,…,对象名 n; (2)类模板名 <模板参数表> 对象名 1(构造函数实参),…,对象名 n(构造函数实参); 4. 如果要定义二元组的类,则需要根据组成二元组的类型定义很多不同的类。 (1)现在可以使用类模板来解决问题。 | ||
类模板 与 继承 ★ | 1. 类之间允许继承,类模板之间也允许继承。 2. 具体来说,类模板和类模板之间、类模板和类之间可以互相继承,它们之间的常见派生关系有以下 4 种情况: (1)普通类继承模板类 (2)类模板继承普通类 (3)类模板继承类模板 (4)类模板继承模板类 |