返回:0200 C++总目录 · 上一课:0200 · 下一课:0202 Chap2 C++简单程序设计

1、资料清单

资料 内容 入口
教材 《C++语言程序设计(第4版)》第 1 章:绪论 抽取 Markdown 下载
课件 第 1 章课件,位于本地郑莉 C++ 资料目录 本地资料夹
例题源代码 C++V5 源代码 下载
VS2019 工程 C++V5 VS2019 solution 下载

本章的定位:不是马上写大量代码,而是先回答三个问题:程序设计语言为什么会发展到 C++面向对象到底在解决什么问题数据在计算机里如何表示和存储

2、颜色标注

颜色 含义 使用位置
蓝色 核心术语、定义 对象、类、封装、补码
绿色 章节主线、理解框架 语言发展、开发流程
黄色 易错点、边界条件 补码位数、二进制换算
红色 必须警惕的误区 把面向对象理解成语法糖

3、学习目标

学完本章后,至少要能完成下面这些事:

目标 要会到什么程度
程序设计语言发展 能说清机器语言、汇编语言、高级语言和面向对象语言的抽象层级
面向对象方法 能用自己的话解释对象、类、封装、继承、多态
结构化方法对比 能说明结构化程序设计的优点,以及它为什么在复杂系统中会吃力
信息表示 能做二进制、十六进制、补码之间的基本转换
程序开发流程 能说清源程序到可执行程序的大致过程

4、章节目录

小节 内容 本节关键词
1.1 计算机程序设计语言的发展 机器语言、汇编语言、高级语言、C++
1.2 面向对象的方法 对象、类、封装、继承、多态
1.3 面向对象的软件开发 OOA、OOD、OOP、OOT、维护
1.4 信息的表示与存储 二进制、十六进制、原码、反码、补码
1.5 程序开发的基本概念 编辑、编译、连接、运行、调试

5、程序设计语言的发展

计算机程序设计语言的发展,本质上是不断提高抽象层次的过程:从直接控制硬件,到用接近自然语言和问题领域的方式描述程序。

阶段 表达方式 特点 局限
机器语言 01 组成的指令 计算机可以直接执行,效率高 难写、难读、依赖硬件
汇编语言 助记符表示机器指令 比机器语言可读,仍接近硬件 可移植性差,开发复杂
高级语言 接近数学表达和自然语言 可读性、可维护性、可移植性更好 需要编译或解释
面向对象语言 用对象、类和消息组织程序 更适合表达复杂系统中的实体关系 需要先理解抽象和建模

可以这样记:机器语言面向机器汇编语言面向指令高级语言面向算法面向对象语言面向问题中的对象

C++ 是在 C 语言基础上发展出来的语言。它一方面保留了 C 语言接近底层、效率高、可控制性强的特点,另一方面引入了类、对象、继承、多态等机制,让大型程序可以更好地组织。

6、面向对象的方法

6.1 对象

对象是系统中用来描述客观事物的基本单位。一个对象通常包含两部分:

组成 含义 例子
属性 对象的静态特征 学生的姓名、学号、成绩
行为 对象可以执行的操作 选课、考试、查询成绩

用一句话说:

1
对象 = 属性 + 行为

例如,假设要描述一个“学生”:

1
2
3
4
5
6
7
8
9
class Student {
public:
void printInfo() const;

private:
std::string name;
int id;
double score;
};

这里 nameidscore 是属性,printInfo() 是行为。

6.2 类

是对同一类对象共同特征的抽象。对象是具体的,类是抽象出来的模板。

概念 解释
抽象模板,规定一类对象有哪些属性和行为
对象 类的实例,是程序运行中真实存在的实体
实例化 根据类创建对象的过程
1
2
Student alice;
Student bob;

Student 是类,alicebob 是两个对象。

6.3 封装

封装就是把对象的属性和行为组织在一起,并隐藏对象内部实现细节,只向外提供必要接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Counter {
public:
void increase() {
value++;
}

int getValue() const {
return value;
}

private:
int value = 0;
};

value 被放在 private 中,外部不能随意修改,只能通过 increase()getValue() 访问。

封装不是把代码藏起来这么简单。 它真正的作用是控制访问边界,让对象内部状态不被外部随便破坏。

6.4 继承

继承用来表达类与类之间的“是一种”关系。子类可以复用父类已有的数据和行为,也可以扩展自己的特性。

1
2
3
4
5
6
7
8
9
class Person {
public:
void breathe();
};

class Student : public Person {
public:
void study();
};

Student 是一种 Person,所以学生拥有人的公共行为,同时又有自己的学习行为。

6.5 多态

多态表示同一个接口在不同对象上表现出不同的行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Shape {
public:
virtual double area() const = 0;
};

class Circle : public Shape {
public:
double area() const override;
};

class Rectangle : public Shape {
public:
double area() const override;
};

同样调用 area(),圆形和矩形会使用各自的面积计算方式。

7、结构化程序设计与面向对象的对比

结构化程序设计强调自顶向下、逐步求精、模块化分解。它适合把问题拆成函数和流程。

方法 组织中心 优点 局限
结构化程序设计 函数和过程 思路清晰,适合算法和流程控制 数据和操作分离,复杂系统维护成本高
面向对象程序设计 对象和类 更贴近问题领域,便于封装和复用 需要先建立合理抽象,设计不当会变复杂

不要把面向对象理解成“把函数放进类里”。 面向对象关注的是对象之间的关系、责任边界和可维护性。

8、面向对象的软件开发

面向对象方法不仅是写代码的方法,也可以贯穿软件工程全过程。

阶段 英文缩写 主要任务
面向对象分析 OOA 分析问题领域中有哪些对象、对象有什么职责
面向对象设计 OOD 设计类、接口、关系、模块边界
面向对象编程 OOP 用 C++ 等语言把设计实现成程序
面向对象测试 OOT 测试类、对象交互和系统行为
面向对象维护 OOSM 修改、扩展、重构已有系统

一个简单顺序可以记成:

1
先识别对象 -> 再设计类 -> 然后写代码 -> 最后测试和维护

9、信息的表示与存储

9.1 计算机内部的信息分类

计算机内部的信息大致可以分成两类:

大类 子类 说明
控制信息 指令、控制字 告诉计算机“做什么、怎么做”
数据信息 数值信息、非数值信息 被处理的对象,如整数、字符、图像、声音

9.2 二进制

二进制是以 2 为基数的计数方式,只使用 01 两个符号,遵循“逢二进一”。

选择二进制的原因 说明
易于物理实现 高低电平、通断状态都能对应 0/1
运算规则简单 加法、乘法、逻辑运算规则更统一
可靠性高 两种状态容易区分,抗干扰能力较强
通用性强 数值、字符、图像、声音都能编码为二进制

缺点也很明显:表示同一个数时,二进制通常比十进制更长。

9.3 进制转换

常用转换方法:

转换 方法
十进制整数转二进制 除 2 取余,逆序排列
二进制转十进制 按位权展开求和
二进制转十六进制 从右向左每 4 位分一组
十六进制转二进制 每 1 位十六进制展开成 4 位二进制

例子:

1
2
3
(93)10 = 64 + 16 + 8 + 4 + 1
= (1011101)2
= (5D)16

9.4 原码、反码、补码

编码 正数 负数 主要特点
原码 符号位为 0,数值位表示绝对值 符号位为 1,数值位表示绝对值 直观,但有 +0-0
反码 与原码相同 符号位不变,其余位取反 仍有 +0-0
补码 与原码相同 反码加 1 便于加减统一,计算机常用

补码一定要说明位数。 比如 -1 在 8 位补码中是 11111111,在 16 位补码中是 11111111 11111111

常用公式:

1
2
3
n 位无符号整数范围:0 到 2^n - 1
n 位补码整数范围:-2^(n-1) 到 2^(n-1)-1
负数 x 的 n 位补码:2^n - |x|

例子:

1
2
-32 的 8 位补码 = 2^8 - 32 = 224 = (11100000)2 = (E0)16
-1 的 16 位补码 = 2^16 - 1 = 65535 = (FFFF)16

10、程序开发的基本概念

一个 C++ 程序从源代码到运行结果,通常经过这些步骤:

步骤 内容 常见文件
编辑 写源代码 .cpp.h
预处理 处理 #include、宏等 中间文件
编译 把源代码翻译为目标代码 .obj.o
连接 把目标代码和库连接成可执行程序 .exe 或可执行文件
运行 执行程序并观察结果 终端输出
调试 定位语法、逻辑、运行错误 断点、单步执行

以后遇到错误时,可以先问一句:这是编译错误连接错误运行错误,还是逻辑错误

11、本章代码复盘

第 1 章以概念为主,可以用下面这段代码复盘“二进制表示”和“补码需要位数”这件事。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <bitset>
#include <iostream>

int main() {
int positive = 93;
signed char negative = -32;
unsigned short allOnes = 65535;

std::cout << "93 in binary: "
<< std::bitset<8>(positive) << '\n';

std::cout << "-32 in 8-bit two's complement: "
<< std::bitset<8>(static_cast<unsigned char>(negative)) << '\n';

std::cout << "65535 in 16-bit binary: "
<< std::bitset<16>(allOnes) << '\n';

return 0;
}

预期输出:

1
2
3
93 in binary: 01011101
-32 in 8-bit two's complement: 11100000
65535 in 16-bit binary: 1111111111111111

12、课后习题答案

以下答案已按复盘笔记重新整理,不再直接堆放 PDF 抽取文字。重点题目补了计算过程和易错提醒。

1-1 简述计算机程序设计语言的发展历程

程序设计语言大致经历了下面几个阶段:

阶段 说明
机器语言 用二进制机器指令编程,计算机可直接执行
汇编语言 用助记符代替机器指令,需要汇编后执行
高级语言 用更接近数学和自然语言的方式编写程序
面向对象语言 用对象、类、封装、继承、多态组织程序

答案要点:语言发展的核心是抽象层次提高,程序员逐渐从机器细节中解放出来。 C++ 属于高级语言,也是一种支持面向对象程序设计的语言。

1-2 面向对象的编程语言有哪些特点

面向对象编程语言的主要特点:

特点 说明
对象建模 直接用对象描述现实世界或问题领域中的实体
类与抽象 抽取同类对象的共同属性和行为,形成类
封装 把数据和操作数据的方法放在一起,并隐藏内部细节
继承 子类复用和扩展父类已有功能
多态 同一接口在不同对象上表现出不同实现
代码复用 通过类库、继承、模板等方式减少重复开发

总结:面向对象语言更适合描述复杂系统,能提高程序的可维护性、可扩展性和可复用性

1-3 什么是结构化程序设计方法?优点和缺点是什么

结构化程序设计是一种面向过程的程序设计方法,强调:

1
2
3
4
自顶向下
逐步求精
模块化分解
顺序、选择、循环三种基本控制结构

优点:

优点 说明
思路清晰 适合把复杂任务拆成多个子任务
易于实现 每个模块可以独立设计和测试
易于维护 功能模块边界较清楚
适合算法流程 对计算过程明确的问题很有效

缺点:

缺点 说明
数据和操作分离 数据结构变化时,相关函数往往都要修改
复用能力较弱 很多逻辑依赖具体流程,难以抽成稳定对象
不适合复杂交互系统 事件驱动、图形界面和大型软件更难用纯流程描述

一句话概括:结构化方法适合过程清晰的算法问题,但在大型复杂系统中,单纯依靠过程分解会越来越难维护。

1-4 什么是对象?什么是面向对象方法?这种方法有哪些特点

对象是系统中描述客观事物的基本单位,由属性和行为组成。

1
对象 = 属性 + 行为

面向对象方法是把数据和操作数据的方法封装成对象,再通过对象之间的消息交互完成系统功能的方法。

主要特点:

特点 解释
抽象 从具体对象中抽取共同特征,形成类
封装 把属性和行为组织成一个整体
继承 子类可以复用父类已有内容
多态 同一操作可以在不同对象中有不同表现
贴近现实 程序结构更接近问题领域本身

1-5 什么叫做封装

封装是把对象的属性和行为结合成一个独立单位,并尽量隐藏对象内部细节,只保留必要接口。

例如:

1
2
3
4
5
6
7
8
9
class BankAccount {
public:
void deposit(double money);
bool withdraw(double money);
double getBalance() const;

private:
double balance;
};

balance 不能被外部随意修改,只能通过 deposit()withdraw()getBalance() 访问。这样可以保护对象内部状态。

答案要点:封装 = 数据 + 操作 + 访问控制。

1-6 面向对象的软件工程包括哪些主要内容

面向对象软件工程包括:

内容 英文缩写 说明
面向对象分析 OOA 分析系统中有哪些对象和职责
面向对象设计 OOD 设计类、关系、接口和模块
面向对象编程 OOP 用语言实现类和对象
面向对象测试 OOT 测试对象、类和对象交互
面向对象维护 OOSM 对已有系统进行修改、扩展和维护

1-7 简述计算机内部的信息可分为几类

计算机内部信息可分为两大类:

大类 小类 作用
控制信息 指令、控制字 控制计算机执行操作
数据信息 数值信息、非数值信息 表示程序要处理的数据

数值信息包括整数、实数等;非数值信息包括字符、图像、声音、逻辑值等。

1-8 什么叫二进制?使用二进制有什么优点和缺点

二进制是基数为 2 的计数方法,只使用 01 两个符号,每一位的权值是 2 的幂。

优点:

优点 说明
易于物理实现 高低电平可以直接表示 0/1
运算简单 规则少,适合逻辑电路
可靠性高 两种状态容易区分
通用性强 各类信息都能编码成二进制

缺点:

缺点 说明
位数较长 同一个数用二进制表示时通常更长
人类阅读不直观 所以常用十六进制压缩表示

1-9 将十进制数转换为二进制和十六进制补码

题目里没有统一给出位数。这里按教材答案习惯处理:-32 使用 8 位补码,65535-1 使用 16 位表示。复盘时一定记住:补码问题必须先看位数。

题号 十进制 二进制 十六进制
1 2 10 2
2 9 1001 9
3 93 1011101 5D
4 -32 11100000 E0
5 65535 11111111 11111111 FFFF
6 -1 11111111 11111111 FFFF

计算说明:

1
2
3
4
5
6
7
8
9
93 = 64 + 16 + 8 + 4 + 1
= 1011101B
= 5DH

-32 的 8 位补码:
2^8 - 32 = 224 = E0H = 11100000B

-1 的 16 位补码:
2^16 - 1 = 65535 = FFFFH

1-10 将以下数值转换为十进制

题号 原数 十进制结果 计算过程
1 (1010)₂ 10 1×2^3 + 1×2^1 = 8 + 2
2 (10001111)₂ 143 128 + 8 + 4 + 2 + 1
3 (01011111 11000011)₂ 24515 0x5FC3 = 5×4096 + 15×256 + 12×16 + 3
4 (7F)₁₆ 127 7×16 + 15
5 (2D3E)₁₆ 11582 2×4096 + 13×256 + 3×16 + 14
6 (F10E)₁₆ 61710 15×4096 + 1×256 + 0×16 + 14

如果把 F10E 当作 16 位有符号补码,它会表示负数;本题教材答案按无符号数值转换,所以结果是 61710

1-11 简要比较原码、反码、补码几种编码方法

编码方式 正数表示 负数表示 特点
原码 符号位 0,数值位为绝对值 符号位 1,数值位为绝对值 直观,但有 +0-0
反码 与原码相同 符号位不变,数值位逐位取反 负数计算比原码方便,但仍有两个零
补码 与原码相同 反码末位加 1 加减法可以统一处理,计算机常用

以 8 位整数 -5 为例:

1
2
3
4
+5 原码:00000101
-5 原码:10000101
-5 反码:11111010
-5 补码:11111011

结论:计算机中整数通常使用补码表示,因为补码能把减法转化为加法,并且只有一个零。

13、本章复盘任务

  1. 用自己的话解释“机器语言、汇编语言、高级语言、面向对象语言”的差别。
  2. 手写一遍对象、类、封装、继承、多态的定义,并各举一个生活例子。
  3. 重新计算 93-32F10E 的进制转换过程。
  4. std::bitset 运行本章代码,观察不同位数下 -1 的表示。
  5. 回答一个问题:为什么 C++ 既适合讲面向对象,又仍然能接近底层?