委托构造函数
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 23 课,共 104 课。
当你有多个构造函数共享相同的初始化逻辑时,可以使用委托构造函数来避免代码重复。委托构造函数会在其初始化列表中调用同一个类的另一个构造函数。
class Player {
std::string name;
int health;
int level;
public:
// 主构造函数负责实际工作
Player(std::string n, int h, int lvl)
: name(n), health(h), level(lvl) {}
// 委托给主构造函数
Player(std::string n) : Player(n, 100, 1) {}
// 默认构造函数也会委托给主构造函数
Player() : Player("Unknown") {}
};委托在初始化列表中完成,使用类名后跟参数。调用 Player() 时,它会委托给 Player(std::string),后者再委托给三参数构造函数。调用链会从目标构造函数开始,返回到最初的构造函数。
有一条重要规则:委托构造函数的初始化列表中不能有其他成员。委托必须是唯一的项目:
class Item {
int id;
int value;
public:
Item(int i, int v) : id(i), value(v) {}
// 错误!不能同时使用委托构造和成员初始化。
// Item(int i) : Item(i, 0), id(i) {}
// 正确:只使用委托构造。
Item(int i) : Item(i, 0) {}
};委托构造函数有助于将初始化逻辑集中在一处,让代码更易于维护,也能减少重复代码导致的错误。
挑战
简单让我们构建一个连接设置系统,演示如何通过串联构造函数调用,让委托构造函数避免代码重复。
你将创建两个文件来整理代码:
Connection.h:定义一个表示网络连接的Connection类,并提供多种配置选项。你的类应包含:- 私有成员:
host(字符串)、port(int)、timeout(以秒为单位的 int)和secure(bool) - 一个主构造函数,接收全部四个参数,并使用初始化列表初始化所有成员。这个构造函数应打印
"Connection configured: <host>:<port>" - 一个只接收
host和port的构造函数,它委托给主构造函数,其中timeout默认为30,secure默认为false - 一个只接收
host的构造函数,它委托给双参数构造函数,其中port默认为80 - 一个默认构造函数,它委托给单参数构造函数,其中
host默认为"localhost" - 一个
getInfo()方法,返回格式为"<host>:<port> (timeout: <timeout>s, secure: <yes/no>)"的字符串
- 私有成员:
main.cpp:通过使用不同的构造函数创建连接,展示委托调用链。读取输入中的主机名和端口号(分别占一行),然后:- 使用默认构造函数创建一个
Connection - 使用输入中的主机创建一个
Connection - 使用输入中的主机和端口创建一个
Connection - 使用输入中的主机、输入中的端口、值为
60的超时时间,以及设为true的安全状态,创建一个Connection - 为每个连接打印
getInfo(),每行一个
- 使用默认构造函数创建一个
委托调用链如下:默认构造函数调用单参数构造函数,单参数构造函数调用双参数构造函数,双参数构造函数再调用主四参数构造函数。这意味着每创建一个对象,都会打印一次 "Connection configured" 消息,而且始终由主构造函数打印。
对于 getInfo() 中的安全状态,如果 secure 为 true,就打印 "yes";否则打印 "no"。
在 main.cpp 中使用 #include "Connection.h" 包含你的头文件。
亲手试试
#include <iostream>
#include <string>
#include "Connection.h"
using namespace std;
int main() {
// 读取输入
string host;
int port;
cin >> host;
cin >> port;
// TODO: 使用默认构造函数创建一个 Connection 对象
// TODO: 只使用输入的 host 创建一个 Connection 对象
// TODO: 使用输入的 host 和 port 创建一个 Connection 对象
// TODO: 使用输入的 host 和 port,以及 timeout=60、secure=true 创建一个 Connection 对象
// TODO: 每行打印一个连接的 getInfo() 结果
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器