13.x — 第 13 章总结和测验

恭喜!你又完成了一章。你所获得的关于结构体的知识将在我们学习 C++ 最重要的主题——类时非常有用!

快速回顾

程序定义类型(也称为用户定义类型)是一种我们可以创建的自定义类型,用于我们自己的程序中。枚举类型和类类型(包括结构体、类和联合体)允许创建程序定义类型。程序定义类型必须在使用前定义。程序定义类型的定义称为类型定义。类型定义不受“单一定义规则”的约束。

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

无作用域枚举之所以这样命名,是因为它们将其枚举器名称放入与枚举定义本身相同的范围(而不是像命名空间那样创建新的作用域区域)。无作用域枚举也为其枚举器提供了一个命名作用域区域。无作用域枚举将隐式转换为整数值。

有作用域枚举的工作方式与无作用域枚举类似,但不会隐式转换为整数,并且枚举器放置在枚举的作用域区域中(而不是放置在定义枚举的作用域区域中)。

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

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

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

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

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

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

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

小测验时间

耶!

问题 #1

在设计游戏时,我们决定要有怪物,因为每个人都喜欢打怪。声明一个表示你的怪物的结构体。怪物应该有一个类型,可以是以下之一:食人魔、龙、兽人、巨型蜘蛛或史莱姆。

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

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

This Ogre is named Torg and has 145 health.
This Slime is named Blurp and has 23 health.

显示答案

问题 #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{};
  // The Player struct is still under development.  More members will be added.
};

显示答案

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

显示答案

i) std::string_view

显示答案

问题 #3

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

int main()
{
	Triad t1{ 1, 2, 3 }; // note: uses CTAD to deduce template arguments
	print(t1);

	Triad t2{ 1.2, 3.4, 5.6 }; // note: uses CTAD to deduce template arguments
	print(t2);

	return 0;
}

并产生以下结果:

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

如果你使用 C++17,你需要提供一个推导指南才能使 CTAD 工作(有关信息,请参阅 13.14 -- 类模板参数推导 (CTAD) 和推导指南)。

显示答案

guest
您的电子邮箱地址将不会被显示
发现错误?请在上方留言!
与勘误相关的评论在处理后将被删除,以帮助减少混乱。感谢您帮助使网站对每个人都更好!
来自 https://gravatar.com/ 的头像与您提供的电子邮箱地址相关联。
有回复时通知我:  
348 评论
最新
最早 最多投票
内联反馈
查看所有评论