总结与小测验

恭喜你!你又完成了一个章节的学习。你在本章中获得的关于结构体的知识将在我们学习C++最重要的主题——类时发挥重要作用!

快速回顾

程序定义类型(也称为用户定义类型)是我们可以为自己的程序创建的自定义类型。枚举类型和类类型(包括结构体、类和联合体)允许创建程序定义类型。程序定义类型必须在使用之前进行定义。程序定义类型的定义称为类型定义。类型定义不受单一定义规则的限制。

枚举(也称为枚举类型或枚举类)是一种复合数据类型,其中所有可能的值都被定义为符号常量(称为枚举器)。枚举是不同的类型,这意味着编译器可以将它们与其他类型区分开来(与类型别名不同)。

未限定作用域的枚举之所以得名,是因为它们将枚举器的名称放入与枚举定义本身相同的作用域中(与命名空间创建新的作用域区域不同)。未限定作用域的枚举还为其枚举器提供了一个命名的作用域区域。未限定作用域的枚举会隐式地转换为整数值。

限定作用域的枚举与未限定作用域的枚举类似,但不会隐式地转换为整数,并且枚举器仅被放入枚举的作用域区域中(而不是枚举被定义的作用域区域中)。

结构体(简称struct)是一种程序定义的数据类型,它允许我们将多个变量捆绑在一起形成一个单一类型。结构体(或类)中包含的变量称为数据成员(或成员变量)。要访问特定的成员变量,我们在结构体变量名和成员名之间使用成员选择运算符(运算符.)(对于普通结构体和结构体的引用),或者使用成员选择指针运算符(运算符->)(对于指向结构体的指针)。

在一般编程中,聚合数据类型(也称为聚合体)是任何可以包含多个数据成员的类型。在C++中,仅包含数据成员的数组和结构体是聚合体。

聚合体使用一种称为聚合初始化的初始化形式,它允许我们直接初始化聚合体的成员。为此,我们提供一个初始化器列表作为初始化器,它只是一个由逗号分隔的值列表。聚合初始化是一种逐成员的初始化方式,这意味着结构体中的每个成员都按照声明顺序进行初始化。

在C++20中,指定初始化器允许你明确指定哪些初始化值映射到哪些成员。成员必须按照它们在结构体中声明的顺序进行初始化,否则会导致错误。

当我们定义一个结构体(或类)类型时,我们可以在类型定义中为每个成员提供一个默认初始化值。这个过程称为非静态成员初始化,初始化值称为默认成员初始化器。

出于性能原因,编译器有时会在结构体中添加间隔(这称为填充),因此结构体的大小可能大于其成员大小的总和。

类模板是用于实例化类类型(结构体、类或联合体)的模板定义。类模板参数推导(CTAD)是C++17的一个特性,它允许编译器从初始化器中推导模板类型参数。

测验时间

好啦!

问题1

在设计一款游戏时,我们决定要加入怪物,因为大家都喜欢与怪物战斗。声明一个代表怪物的结构体。怪物的类型可以是以下几种之一:食人魔、龙、兽人、巨型蜘蛛或史莱姆。

每个单独的怪物还应该有一个名字(使用std::string),以及一个表示生命值的数值,该数值代表它们在死亡前可以承受的伤害量。编写一个名为printMonster()的函数,用于打印出结构体的所有成员。使用初始化器列表初始化一个食人魔和一个史莱姆,并将它们传递给printMonster()。

你的程序应该产生以下输出:

这个食人魔的名字是Torg,生命值为145。
这个史莱姆的名字是Blurp,生命值为23。

显示答案

问题2

请指定以下每种类型的对象应该按值传递、按常量地址传递还是按常量引用传递。你可以假设接受这些类型作为参数的函数不会修改它们。

a) char

显示答案

b) std::string

显示答案

c) unsigned long

显示答案

d) bool

显示答案

e) 枚举类型

显示答案

f)

struct Position
{
    double x{};
    double y{};
    double z{};
};

显示答案

g)

struct Player
{
    int health{};
    // Player结构体仍在开发中。将添加更多成员。
};

显示答案

h) int(当null是有效参数时)

显示答案

i) std::string_view

显示答案

问题3

创建一个名为Triad的类模板,该模板有3个相同模板类型的成员。同时创建一个名为print的函数模板,用于打印Triad。以下程序应该可以编译:

int main()
{
    Triad t1{ 1, 2, 3 }; // 注意:使用CTAD推导模板参数
    print(t1);

    Triad t2{ 1.2, 3.4, 5.6 }; // 注意:使用CTAD推导模板参数
    print(t2);

    return 0;
}

并产生以下结果:

[1, 2, 3][1.2, 3.4, 5.6]

如果你使用的是C++17,你需要为CTAD提供一个推导指南(参见13.14——类模板参数推导(CTAD)和推导指南,了解相关信息)。

显示答案

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"