12-1 复合数据类型简介
在第4.1 课——基本数据类型简介中,我们介绍了基本数据类型,即 C++ 作为核心语言的一部分提供的基本数据类型。
到目前为止,我们已经在程序中大量使用了这些基本类型,尤其是int数据类型。虽然这些基本类型对于简单的应用非常有用,但当我们开始处理更复杂的任务时,它们就无法满足我们的全部需求了。
例如,假设你要编写一个数学程序来计算两个分数相乘。你会如何在程序中表示分数呢?你可能会使用一对整数(一个表示分子,一个表示分母),像这样:
#include <iostream>
int main()
{
// Our first fraction
int num1 {};
int den1 {};
// Our second fraction
int num2 {};
int den2 {};
// Used to eat (remove) the slash between the numerator and denominator
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;
}
以及该程序的运行:

虽然这个程序可以运行,但它也给我们带来了一些需要改进的地方。首先,每对整数之间的联系都很松散——除了注释和代码中的使用上下文之外,几乎没有任何迹象表明每对分子和分母之间存在关联。其次,遵循 DRY(不要重复自己)原则,我们应该创建一个函数来处理用户输入的分数(以及一些错误处理)。然而,函数只能返回一个值,那么我们如何将分子和分母返回给调用者呢?
现在想象一下另一种情况:你需要编写一个程序来维护员工 ID 列表。你会怎么做呢?你可以尝试这样的方法:
int main()
{
int id1 { 42 };
int id2 { 57 };
int id3 { 162 };
// and so on
}
但如果你的员工有 100 人呢?首先,你需要100 个变量名。如果需要打印所有变量名呢?或者需要将它们传递给函数呢?那将需要大量的输入。这种方法根本无法扩展。
显然,基本类型只能满足我们一定的需求。
复合数据类型
幸运的是,C++ 支持第二组数据类型:复合数据类型(有时也称为组合数据类型)。复合数据类型是根据其他现有数据类型定义的。它们具有额外的属性和行为,使其在解决某些类型的问题时非常有用。
关键见解:
每种数据类型要么是基本类型,要么是复合类型。C++ 语言标准明确定义了每种类型所属的类别。
正如我们将在本章和后续章节中展示的那样,我们可以使用复合数据类型来优雅地解决我们上面提出的所有挑战。
C++ 支持以下复合类型:
- 函数
- C 风格数组
- 指针类型:
- 指向对象的指针
- 函数指针
- 指向成员类型的指针:
- 指向数据成员的指针
- 指向成员函数的指针
- 引用类型:
- L值引用
- R值引用
- 枚举类型:
- 无作用域枚举
- 作用域枚举
- 类类型:
- 结构体
- 类
- 联合体
你其实已经经常使用一种复合类型:函数。例如,考虑以下函数:
void doSomething(int x, double y)
{
}
此函数的类型为void(int, double)。请注意,此类型由基本类型组成,因此它是一个复合类型。当然,函数也有其自身的特殊行为(例如,可调用性)。
由于这里需要涵盖的内容很多,我们将分多章讲解。本章我们将介绍一些比较简单的复合类型,包括 l-value references、和 pointers。下一章我们将介绍unscoped enumerations、scoped enumerations 以及我们的第一个类类型: structs。之后的章节中,我们将介绍类并深入探讨一些更有用的array类型。这包括std::string(在 5.7 课——std::string 简介中介绍),它实际上就是一个类类型!
命名法:
类类型是指结构体、类或联合体类型的类型。我们将在以后的课程中频繁使用这个术语。
准备好战斗了吗?出发!

浙公网安备 33010602011771号