我们介绍了基本数据类型(fundamental data types),它们是 C++ 核心语言直接提供的最基础数据类别。
迄今为止,我们的程序大量使用这些基本类型,特别是 int
。然而,随着需求变得复杂,仅靠基本类型已无法覆盖所有场景。
示例 1:分数运算
假设你正在编写一个用于计算两个分数乘积的数学程序。如何在程序中表示一个分数?你可能会使用一对整数——一个分子、一个分母:
#include <iostream>
int main()
{
// 第一个分数
int num1 {};
int den1 {};
// 第二个分数
int num2 {};
int den2 {};
// 用于吃掉分子与分母之间的斜杠
char ignore {};
std::cout << "Enter a fraction: ";
std::cin >> num1 >> ignore >> den1;
std::cout << "Enter a fraction: ";
std::cin >> num2 >> ignore >> den2;
std::cout << "The two fractions multiplied: "
<< num1 * num2 << '/' << den1 * den2 << '\n';
return 0;
}
示例运行:
Enter a fraction: 1/2
Enter a fraction: 3/4
The two fractions multiplied: 3/8
虽然程序能跑,但存在两个问题:
- 每对整数之间仅靠注释和上下文暗示其关联,耦合度低;
- 遵循 DRY(Don’t Repeat Yourself)原则时,应把输入分数封装成函数,但函数只能返回一个值,如何同时返回分子与分母?
示例 2:员工 ID 列表
若需保存 100 位员工的 ID,你可能会这样写:
int main()
{
int id1 { 42 };
int id2 { 57 };
int id3 { 162 };
// ……
}
但面对 100 名员工时,你需要输入 100 个变量名,打印或传参时更是一场灾难。显然,基本类型无法胜任规模扩展。
复合数据类型
好在 C++ 提供了复合数据类型(compound / composite data types):以现有类型为基础构造的新类型,具备额外属性与行为,专门解决此类问题。
关键要点
所有数据类型要么为基本类型,要么为复合类型。C++ 标准明确定义了每一类型所属类别。
本章及后续章节将展示如何利用复合类型优雅地解决上述难题。
C++ 支持的复合类型概览
- 函数
- C 风格数组
- 指针类型
‑ 对象指针
‑ 函数指针
‑ 成员指针(数据成员 / 成员函数) - 引用类型
‑ 左值引用
‑ 右值引用 - 枚举类型
‑ 非限定枚举
‑ 限定枚举 - 类类型
‑ struct
‑ class
‑ union
你已频繁使用其中一种复合类型:函数。例如:
void doSomething(int x, double y)
{
}
其类型为 void(int, double)
,由基本类型组合而成,故为复合类型。函数还具备“可调用”等特殊行为。
鉴于内容繁多,我们将分章节展开:
- 本章:左值引用、指针等较简单的复合类型;
- 下一章:非限定/限定枚举及首个类类型——
struct
; - 后续章节:深入类类型并介绍实用数组类型,包括 5.7 课将引入的
std::string
(本质上也是类类型)。
术语
“类类型”统指 struct
、class
或 union
,后续课程将频繁使用。
准备好了吗?让我们启程!