二级 C++ 语言程序设计
科目 61 · 考点与真题
C++ 是二级考试中面向对象程序设计的主流科目,它考的是语言基础 + 类与对象 + 继承与多态 + 运算符重载 + 模板 + 流 + 公共基础知识。 其中最难啃、也最常考的是构造函数与析构函数、继承方式与构造顺序、虚函数与动态绑定——选择题和操作题都会出现。 本页按 2025 年版官方大纲组织知识点,并收录 2021–2026 年真题与官方样题。
选择题 40 分中含 公共基础知识 10 分;操作题 60 分 = 基本操作题 + 简单应用题 + 综合应用题,均为上机编程。 开发环境为 Visual C++ 2010 学习版,答题前需熟悉"解决方案 + main.cpp"的项目结构。
C++ 语言概述
选择题必考 · ★★★★大纲要求:C++ 语言的特点及基本符号;关键字、常量、运算符与标点符号的含义;标识符的组成规则;C++ 程序的基本框架;Visual C++ 2010 学习版环境的使用。
语言特点与基本符号
- 面向对象三大特征:封装(class)、继承(derivation)、多态(virtual 动态绑定)
- 与 C 语言兼容,支持过程化与面向对象两种风格;支持函数重载、模板、命名空间、流式 I/O
- C++ 基本符号:关键字(class、virtual、friend、template、new、delete、this、inline 等)、标识符、运算符、标点符号({ } ( ) ; ,)
- 注释:
//单行;/* ... */多行
标识符组成规则(官方样题)
C++// 合法标识符:由字母、数字、下划线组成,不能以数字开头,不能与关键字同名 _radius // 合法:以下划线开头 foo~bar // 非法:~ 不是字母/数字/下划线 else // 非法:是关键字 3room // 非法:以数字开头 // 常见关键字:class public protected private virtual friend template typename // new delete this inline const static namespace using // 注意:cin / cout 不是关键字,是标准库流对象名;function 也不是关键字
foo~bar(含 ~)、else(关键字)、3room(数字开头)均非法。
程序基本框架
C++#include <iostream> // 输入输出流头文件 using namespace std; // 使用标准命名空间(否则写 std::cout) int main() { cout << "Hello, C++!" << endl; return 0; // 0 表示正常结束 } // 结构:头文件区 → 命名空间 → 全局声明 → main 函数 → 其他函数 // 操作题在 VC++ 2010 中以"解决方案 proj1 + main.cpp"形式给出
<iostream> 提供 cin/cout;
endl 输出换行并刷新缓冲区;using namespace std; 可省略为 std::cout。
数据类型、运算符与表达式
选择题高频 · ★★★★★大纲要求:基本类型、派生类型与用户定义类型;各类常量的表示;变量的定义、初始化、作用域与生存期、4 种存储类型;运算符的优先级与结合性;表达式的求值规则。
数据类型总览
| 类别 | 类型 | 说明 |
|---|---|---|
| 基本类型 | char | 字符型,1 字节 |
short / int / long | 整型,VC++2010 下 int 占 4 字节 | |
float / double | 单/双精度浮点 | |
bool | 逻辑型,取值 true / false(输出 1 / 0) | |
void | 无值类型,用于函数返回"无值" | |
| 派生类型 | 数组、指针、引用、枚举 enum | 由基本类型派生 |
| 用户定义类型 | 结构体 struct / 类 class / 共用体 union | struct 默认公有,class 默认私有 |
常量与变量
- 整型常量:十进制
123;八进制 0 开头0123(=83);十六进制 0x 开头0x1e1f1 - 实型常量:
3.14、1e3(=1000.0)、-1E3;字符常量:'a'、'\n'、'\0' - 字符串常量:
"abc"末尾自动加'\0';逻辑常量:true/false - 符号常量:
const int buffer = 256;(编译期类型检查);#define PI 3.14(宏替换) - 枚举常量:
enum Color {Red, Green, Blue};依次取值 0,1,2 - 变量:定义时可初始化;全局变量在函数外定义、局部变量在函数内定义;存储类型
auto(默认)、register、static、extern
运算符优先级(从高到低)
C++// 口诀:域解析 → 括号/下标 → 单目 → 算术 → 关系 → 逻辑 → 三目 → 赋值 → 逗号 :: . -> () [] // 最高 ! ~ ++ -- - * & (类型) new delete // 单目(右结合) * / % // 乘除取余 + - // 加减 << >> // 移位(同时也是流插入/提取运算符) < <= > >= // 关系 == != // 相等 && // 逻辑与 || // 逻辑或 ? : // 三目 = += -= *= /= %= // 赋值(右结合) , // 逗号(最低)
易错计算题
C++// 整除与取余:整数相除仍为整数;% 两侧必须是整数 5 / 2 // 2;5.0 / 2 = 2.5(有浮点参与 → 浮点结果) 5 % 2 // 1 // 自增自减:++i 先加后用;i++ 先用后加 int i = 3, x; x = i++; // x = 3,i = 4 x = ++i; // i = 5,x = 5 // 逻辑表达式结果是 true/false;0<a<2 是 (0<a)<2,不是 a 的范围判断! 0 < a < 2 // 等价于 (0<a)<2:a>0 时 1<2 恒真(经典陷阱) // 类型转换:小→大自动提升;大→小需显式转换 double d = 3.14; int n = static_cast<int>(d); // n = 3
基本控制结构
操作题核心 · ★★★★★大纲要求:C++ 基本语句;顺序、选择(if / switch)、循环(for / while / do-while)结构;break、continue、return 跳转语句;选择与循环的嵌套。
三种循环对比
| 循环 | 判断时机 | 最少执行次数 | 典型场景 |
|---|---|---|---|
while(条件) | 先判断 | 0 次 | 条件循环 |
do{...}while(条件) | 后判断 | 1 次 | 至少执行一次 |
for(初始化;条件;更新) | 先判断 | 0 次 | 计数循环;for(;;) 为无限循环 |
switch 的 break 穿透
C++switch (b) { case 1: cout << "A"; break; case 2: cout << "B"; // 无 break:继续往下执行 case 3: cout << "C"; break; default: cout << "D"; } // b=2 → 输出 BC(穿透到 case 3 的 break 才停)
break / continue / return
break:跳出当前层循环或 switch;嵌套中只跳一层continue:跳过本次循环剩余语句,进入下一轮return:结束整个函数并返回;在 main 中结束程序
官方样题:do-while 追踪
C++int x = 3; do { x -= 2; cout << x; } while (!(--x)); // 第 1 轮:x=1,输出 1;--x 后 x=0,!0=1 真 → 继续 // 第 2 轮:x=-2,输出 -2;--x 后 x=-3,!(-3)=0 假 → 结束 // 输出:1-2 → 官方样题 03 选 C
int k=1,num=26; do{k*=num%10; num/=10;} while(num);
运行后 k 的值 → B)12。追踪:第 1 轮 k=6、num=2;第 2 轮 k=12、num=0 结束。
数组、指针与引用
选择+操作双核心 · ★★★★★大纲要求:一维/多维数组的定义、初始化和访问;string 类型与字符数组、常用字符串函数;指针的概念与基本运算;引用的定义、初始化与使用;new / delete 动态存储分配。
数组
C++int a[5]; // 5 个元素,下标 0~4;a[5] 越界 int b[] = {1, 2, 3}; // 初始化时可省略长度 int m[3][4]; // 二维数组:3 行 4 列,按行存储 cout << a[0] << b[2] << m[1][2];
string 与字符数组
C++#include <string> // string 类头文件 #include <cstring> // C 风格字符串函数(strlen 等) string s = "hello"; // 直接赋值、比较、拼接:s + "!" char c[] = "abc"; // 长度 4:'a' 'b' 'c' '\0' strlen(c); // 3(不含 '\0') strcpy(s1, s2); strcmp(a, b); strcat(d, s); // 复制/比较/拼接
指针与动态分配
C++int x = 5; int *p = &x; // & 取地址;*p 解引用 → 5 int a[4]; int *q = a; // 数组名是首地址;a[i] 等价于 *(a+i) int *r = new int(5); // 动态分配单个 int 并初始化为 5 int *s = new int[10]; // 动态分配 10 个 int 的数组 delete r; // 释放单个对象 delete [] s; // 释放数组(必须带 [])
引用
C++int x = 5; int &r = x; // r 是 x 的别名:必须定义时初始化,绑定后不可改 r = 10; // x 变成 10 void swap(int &a, int &b) { // 引用参数:修改的就是实参 int t = a; a = b; b = t; }
new int(5) = 分配 1 个 int 且值 5;new int[5] = 分配 5 个 int 的数组;
new int = 分配 1 个 int 未初始化。引用必须初始化且不能改变绑定,是"别名"不是拷贝。
函数
选择+操作双核心 · ★★★★★大纲要求:函数定义与调用、函数原型与返回类型、参数传递方式与默认参数、函数重载、内联函数、递归函数。
函数原型与参数传递
C++int add(int a, int b); // 函数原型声明(调用前必须先声明或定义) int add(int a, int b) { // 定义 return a + b; } // 值传递:形参是实参的拷贝,函数内修改不影响实参 // 引用/指针传递:函数内修改影响实参(swap 场景) // 默认参数:从右向左连续设置,void f(int a, int b=2, int c=3);
函数重载
C++void fun(int val) { cout << "int"; } void fun(double val) { cout << "double"; } void fun(int v1, double v2) { cout << "int+double"; } fun(1); // 调用第一个 → 输出 int(按实参类型匹配) // 重载条件:参数个数或类型不同;与返回值类型无关!
内联函数
C++inline int sq(int x) { return x * x; } // inline 只是向编译器"建议"在调用处展开,省去函数调用开销 // 适合短小、频繁调用的函数;递归函数不适合做内联 // 注意:内联函数 ≠ 定义在另一个函数体内部的函数(那是嵌套,C++ 不允许)
类和对象
全卷核心 · ★★★★★大纲要求:类与对象的概念、数据成员/成员函数与访问控制;构造函数与析构函数(初始化列表、默认构造、复制构造);this 指针;静态成员;常对象与常成员函数;友元;成员对象;对象数组与自由存储对象。
类定义与访问控制
C++class Point { private: // 默认访问权限:private int xx, yy; public: Point() : xx(0), yy(0) {} // 构造函数(初始化列表) Point(int x, int y = 0) : xx(x), yy(y) {} // 重载 + 默认参数 int getX() const { return xx; } // 常成员函数 }; Point a(2), b[3]; // 对象、对象数组:a 调 1 次构造,b 调 3 次
构造函数与析构函数
| 构造函数 | 析构函数 | |
|---|---|---|
| 名称 | 与类同名,可重载 | ~类名,不能重载,一个类仅一个 |
| 参数/返回 | 可有参数,无返回类型 | 无参数、无返回值 |
| 时机 | 对象创建时自动调用 | 对象生命周期结束时自动调用 |
| 特殊形态 | 默认构造、复制构造(参数为本类引用) | 可声明为 virtual(虚析构) |
- 复制构造函数在对象按值传给函数、按值返回对象、用对象初始化另一对象时被调用
- 编译器仅在类没有定义任何构造函数时才自动生成默认构造函数
- 静态数据成员:必须在类外单独定义和初始化(
int Test::b = 0;),所有对象共享一份 - 静态成员函数:只能访问静态成员;没有 this 指针
this 指针 / 常对象 / 友元
C++class Test { private: int a; public: void set(int v) { this->a = v; } // this 指向当前对象(非静态成员函数都有) int get() const { return a; } // const 成员函数:不能修改数据成员 friend void show(const Test &t); // 友元函数:可访问私有成员,无 this 指针 }; const Test t; // 常对象:只能调用常成员函数(const 成员函数)
int getValue() const {return a;}。
① 返回类型不匹配(&a 是 int*);③ const 成员函数中修改 a 非法;④ 友元函数不能是 const 成员。
继承和派生
全卷核心 · ★★★★★大纲要求:派生类的定义;不同继承方式下派生类对基类成员的访问;派生类构造与析构;多继承二义性与虚基类;子类型关系与多态;虚函数、纯虚函数、抽象类、虚析构函数。
继承方式与访问控制
| 基类成员 | public 继承 | protected 继承 | private 继承 |
|---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | 不可访问(永远不能被子类直接访问) | ||
C++class B { public: void fun1(){} private: void fun2(){} protected: void fun3(){} }; class D : public B { ... }; // D 的对象 obj:只能访问 public 的 fun1;fun2 私有不可访问; // fun3 是 protected,D 的成员函数可访问,但"对象"不能直接访问
构造与析构顺序(高频)
C++class A{ public: A(){cout<<"A";} ~A(){cout<<"~A";} }; class B : public A { A *p; public: B(){cout<<"B"; p = new A();} ~B(){cout<<"~B"; delete p;} }; B obj; // 构造:基类 A → 派生类 B 体 → 成员(p=new A) 输出:ABA // 析构:~B(delete p 触发 ~A)→ 基类 ~A 输出:~B~A~A // 合计:ABA~B~A~A → 官方样题 23 选 B
虚函数与多态
C++class Base { public: void fun1(){ cout << "Base\n"; } // 非虚 virtual void fun2(){ cout << "Base\n"; } // 虚函数 }; class Derived : public Base { public: void fun1(){ cout << "Derived\n"; } // 隐藏 void fun2(){ cout << "Derived\n"; } // 覆盖(重写) }; void f(Base &b) { b.fun1(); b.fun2(); } Derived obj; f(obj); // fun1 非虚:编译期绑定 → Base;fun2 虚:运行期按实际对象 → Derived // 输出:Base / Derived → 官方样题 26 选 B
- 纯虚函数:
virtual void f() = 0;;含纯虚函数的类是抽象类,不能实例化对象 - 虚函数:不能是静态成员函数(官方样题 16 选 B);通过基类指针/引用调用实现运行时多态
- 虚析构函数:基类析构声明为 virtual,保证通过基类指针 delete 派生类对象时正确调用派生析构
- 多重继承:构造顺序按基类声明顺序(不是初始化列表顺序);同名成员产生二义性时用虚基类 virtual 解决
运算符重载
选择+简单应用 · ★★★★大纲要求:运算符重载的概念与注意事项;典型运算符的重载方式;作为成员函数与非成员函数(友元)重载的两种形态。
重载规则与限制
- 只能重载 C++ 中已有的运算符,不能定义新运算符(官方样题 07 选 C)
- 不能改变运算符的优先级和操作数个数
- 不能重载的运算符:
.(成员访问)、::(域解析)、.*、?:(三目)、sizeof - 不能重载为友元函数的:
=(赋值)、()(函数调用)、[](下标)、->(成员访问)——只能作为成员函数(官方样题 09 选 A)
成员函数 vs 友元函数重载
C++// 双目运算符:成员函数重载时,左操作数由 this 提供,显式参数只需 1 个 class Complex { public: Complex operator+(const Complex &c) const; // 成员:1 个参数 friend Complex operator-(const Complex &a, const Complex &b); }; // 友元:2 个参数 // 前缀 ++ 与后缀 ++:后缀多一个 int 哑元(仅用于区分) Complex &operator++(); // 前缀 ++a Complex operator++(int); // 后缀 a++
流提取 >> / 流插入 << 重载
C++class MyClass { private: int data; public: friend istream& operator>>(istream& is, MyClass& a) { is >> a.data; // 友元:才能访问私有 data return is; } }; // 要点:第一参数是 istream&(返回引用才能连续 >>);第二参数必须是"引用"才能改对象 // 官方样题 12 选 A:friend istream& operator>>(istream& is, MyClass& a);
模板
选择题固定 · ★★★大纲要求:函数模板的概念与机制、定义和使用方式;类模板的概念与机制、定义和使用方式。
函数模板
C++template <typename T> T max2(T a, T b) { return a > b ? a : b; } max2(3, 5); // 由实参推断 T=int max2(2.5, 1.8); // T=double // 显式指定模板实参:cast<double,int>(i) 把 i 由 int 转成 double template <typename T, typename U> T cast(U u) { return (T)u; } // 官方样题 28 选 D
类模板
C++template <typename T> class Stack { private: T data[100]; int top; public: Stack() : top(0) {} void push(const T &v) { data[top++] = v; } }; Stack<int> si; // 用 int 实例化 → 编译器据此生成一个 Stack<int> 类 Stack<double> sd;
C++ 流(输入输出与文件)
选择+综合应用 · ★★★★大纲要求:C++ 流的体系结构、预定义流对象、提取/插入运算符;默认格式与常用格式控制标志;文件流的建立与关闭。
流类体系与预定义对象
| 流类 | 预定义对象 | 用途 |
|---|---|---|
istream | cin | 标准输入(键盘),提取运算符 >> |
ostream | cout / cerr / clog | 标准输出(屏幕),插入运算符 << |
fstream / ifstream / ofstream | — | 文件输入输出流 |
格式控制(iomanip)
C++#include <iomanip> cout << setw(10) << 123; // setw:设置"下一个"输出项的宽度,一次性(非粘性) cout << setprecision(3) << 3.14159; // 精度(小数位数/有效数字) cout << setfill('*') << setw(5) << 12; // 填充字符 → "***12" cout << hex << 255; // 十六进制 ff;dec 十进制;oct 八进制
文件流
C++#include <fstream> ifstream fin("file.dat"); // 输入文件流:默认 ios_base::in(官方样题 30 选 A) ofstream fout("file.dat"); // 输出文件流:默认 ios_base::out fstream fio("f.dat", ios_base::in | ios_base::out); // 读写 ifstream fin; fin.open("file.dat"); // 先定义再 open if (!fin) { /* 打开失败处理 */ } int x; fin >> x; // 从文件读 fout << "hello" << x; // 写入文件 fin.close(); fout.close();
open 返回 void,不能用来初始化对象。正确写法见上(构造、先定义再 open、指针 new 三种)。
公共基础知识(10 分)
性价比最高 · ★★★★★选择题前 10 道是公共基础知识(数据结构、程序设计基础、软件工程、数据库),题目相对固定,背熟考点就能拿分,是过关的"保底分"。
数据结构
| 结构 | 存取方式 | 类别 |
|---|---|---|
| 栈 | 先进后出(FILO),只在一端操作 | 线性结构 |
| 队列 | 先进先出(FIFO) | 线性结构 |
| 线性表 / 链表 | 顺序或链式存储 | 线性结构 |
| 二叉树 / 树 / 图 | 分支/网状关系 | 非线性结构 |
- 二叉树性质:叶子结点数 N0 = N2 + 1;第 k 层最多
2^(k-1)个结点;深度 h 最多2^h - 1个 - 算法复杂度:时间与空间复杂度;堆排序
O(n·log n)、希尔排序O(n^1.5)(最坏较高)
程序设计 / 软件工程 / 数据库
- 结构化程序设计三原则:自顶向下、逐步求精、模块化;三种基本控制结构:顺序、选择、循环
- 模块划分准则:高内聚、低耦合;数据流图(DFD)用于需求分析阶段
- 测试:白盒(逻辑路径)/ 黑盒(等价类划分、边界值分析)
- 数据库系统核心:DBMS;E-R 图:实体矩形、属性椭圆、联系菱形;关系模型用二维表
备考优先级与复习路线
策略时间有限时按下面的优先级投入:先啃类与对象、继承多态这两大核心,再攻操作题三题型。
| 优先级 | 内容 | 理由 |
|---|---|---|
| ★★★★★ | 类与对象、继承与派生、虚函数与多态 | 选择 + 操作题双核心,简单应用几乎必考 |
| ★★★★ | 运算符重载、函数、数组指针与引用 | 选择题高频;基本操作题常考改错 |
| ★★★★ | 公共基础知识 10 分 | 记忆性内容,背熟即得分,成本最低 |
| ★★★ | 模板、C++ 流、数据类型与运算符 | 以选择题为主,考点固定 |
操作题三种题型(60 分)
- 基本操作题:给定类定义,改正
//ERROR**********found**********标记行(常见:缺返回类型、const 误用、调用写法错误) - 简单应用题:在横线处填写代码(常见:派生类声明、构造函数初始化列表、print 函数重写),不能改动其他部分
- 综合应用题:在
//*******333*******与//*******666*******之间编写函数(常见:运算符重载、类方法实现) - 答题环境:Visual C++ 2010 学习版,编译运行通过后再提交;注意分号、括号配对与变量类型
真题题库(2021–2026)
点击选项即判分题库分六个年份标签。2021–2024 为公开网络题库的历年真题(考生回忆/整理版);2025 为中国教育考试网发布的官方样题(依据 2025 年版大纲);2026 为按 2025 大纲编写的模拟题。 点击选项立即判分,自动显示参考答案与解析。
cout << setw(10) << 123; 中,setw(10) 的作用是?operator++(int) 时,int 形参的作用是?virtual void f() = 0;)时,这个类是?ofstream 流类定义流对象并打开一个磁盘文件时,文件的默认打开方式是?int x=3; do { x-=2; cout<<x; } while(!(--x)); 运行时的输出结果是?B obj; 的运行输出结果是?Stack<int> s; 能正确实例化,正确的声明是?The value is 5
The value is 10
参考答案(改错要点)
C++class MyClass { int value; public: MyClass(int v) : value(v) {} // found 常见错误:缺返回类型/构造名写错 int getValue() const { return value; } // found:const 误加/返回类型错 }; // 程序段调用处:MyClass a(5), b(10); cout << "The value is " << a.getValue() << endl; cout << "The value is " << b.getValue() << endl; // 只改 found 标注的那一行,不要动其他内容
Name:Sally Smith
Dept:Sales
Level:2
参考答案(填空要点)
C++class Manager : public Employee { // 填空 1:公有派生类声明 int level; public: Manager(const string &n, const string &d, int l) : Employee(n, d), level(l) {} // 填空 2:初始化列表调基类构造 void print() const { // 填空 3:重写 print(隐藏基类同名函数) Employee::print(); // 先输出姓名和部门 cout << "Level:" << level << endl; } }; // 派生类中与基类同名的成员函数会"隐藏"基类版本,调用时用作用域限定符 Employee::print 访问
参考答案(完整函数)
C++Matrix operator+(const Matrix &m1, const Matrix &m2) { Matrix c(m1.rows, m1.cols); // 与 m1 同尺寸的结果矩阵 for (int i = 0; i < m1.rows; i++) for (int j = 0; j < m1.cols; j++) c.data[i][j] = m1.data[i][j] + m2.data[i][j]; // 对应元素相加 return c; } // 要点:返回新矩阵(值返回);先构造结果对象再逐元素相加; // 成员名(rows/cols/data)以题给类定义为准,不能自己改名