构造函数初始化列表
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 22 课,共 104 课。
你已经在前面的课中见过冒号语法,例如 Player(std::string n, int h) : name(n), health(h) {}。这称为成员初始化列表,也是在 C++ 中初始化成员的首选方式。
初始化列表位于构造函数的参数列表之后,以冒号开头。每个成员都直接用对应的值初始化,并用逗号分隔:
class Rectangle {
int width;
int height;
const int id;
int& reference;
public:
Rectangle(int w, int h, int i, int& r)
: width(w), height(h), id(i), reference(r) {
// 构造函数体(可以为空)
}
};为什么要使用初始化列表,而不是在构造函数体中赋值?使用赋值时,成员会先默认构造,然后再赋予新值。使用初始化列表时,成员会直接用正确的值构造出来,效率更高,有时也是必需的。
某些成员必须使用列表进行初始化:
const成员,在构造后无法赋值
- 引用成员必须在初始化时绑定
- 没有默认构造函数的成员
class Player {
const int maxHealth; // 必须使用初始化列表
std::string name;
public:
// 这样写可以
Player(int max, std::string n) : maxHealth(max), name(n) {}
// 这样写无法编译:
// Player(int max) { maxHealth = max; } // 错误!
};成员会按照它们在类中声明的顺序初始化,而不是按照它们在初始化列表中的顺序。始终按照声明顺序编写初始化列表,避免混淆。
挑战
简单让我们为游戏引擎构建一个配置系统,展示成员初始化列表在什么情况下以及为什么必不可少。你将创建一个 GameConfig 类,其中的成员必须使用初始化列表语法进行初始化。
你将创建两个文件来组织代码:
GameConfig.h:定义一个用于存储游戏设置的GameConfig类。你的类应包含:- 一个
const std::string gameName:游戏标题,创建后不能更改 - 一个
const int maxPlayers:最大玩家人数,在构造时确定 - 一个
int& difficultyRef:对外部难度设置的引用 - 一个
int screenWidth和一个int screenHeight:用于显示设置的普通成员 - 一个接受所有必要参数的构造函数,并使用初始化列表初始化每个成员。初始化列表中的顺序应与成员在类中的声明顺序一致
- 一个
display()方法,按以下格式输出配置:Game: <gameName> Max Players: <maxPlayers> Difficulty: <difficultyRef value> Resolution: <screenWidth>x<screenHeight>
- 一个
main.cpp:从输入中读取配置值,并创建一个 GameConfig 对象。你需要:- 从输入中读取游戏名称(字符串)、最大玩家人数(int)、难度(int)、宽度(int)和高度(int),每项各占一行
- 创建一个本地
int变量来存储难度,供配置对象引用 - 使用初始化列表构造函数创建一个
GameConfig对象 - 调用
display()显示初始配置 - 直接修改难度变量(将它乘以 2)
- 输出
"After difficulty change:" - 再次调用
display(),显示引用如何反映更新后的值
这个挑战说明了初始化列表为什么重要:你的 const 成员和引用成员不能在构造函数体中赋值,必须在初始化列表中进行初始化。引用成员还展示了对原始变量的修改如何通过配置对象反映出来。
使用 #include "GameConfig.h" 在 main.cpp 中包含头文件。
亲手试试
#include <iostream>
#include <string>
#include "GameConfig.h"
using namespace std;
int main() {
// 读取输入值
string gameName;
getline(cin, gameName);
int maxPlayers;
cin >> maxPlayers;
int difficulty;
cin >> difficulty;
int width;
cin >> width;
int height;
cin >> height;
// TODO: 使用初始化列表构造函数创建 GameConfig 对象
// 构造函数应接收:gameName、maxPlayers、difficulty(按引用传递)、width、height
// TODO: 调用 display() 显示初始配置
// TODO: 直接修改 difficulty 变量(将其乘以 2)
// TODO: 输出 "After difficulty change:"
// TODO: 再次调用 display() 显示更新后的配置
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器