特殊方法
在 C++ 中有两种具有特殊意义的方法:构造函数和析构函数。
构造函数
构造函数是一种特殊方法,当对象被创建时调用——它开始了一个对象的生命周期。
使用构造函数的主要原因之一是根据外部参数设置对象的数据成员。例如,当创建一个 `Player` 对象时,构造函数可以用于强制传递给构造函数的生命值在 `0` 和 `maxHealth` 值之间。构造函数可以定义如下
struct Player
{
int maxHealth;
int health;
Player(int maxHp, int hp)
{
maxHealth = maxHp;
health = std::max(std::min(hp, maxHealth), 0);
}
};
此构造函数使用 `max` 和 `min` 函数来确保 `health` 在 `0` 和 `maxHealth` 之间。这样,即使用户尝试传递大于 `maxHealth` 的 `hp`,它也会自动钳制到 `maxHealth`。
构造函数通过创建与类同名且没有返回类型(甚至不是 `void`)的函数来定义。
在 C++ 中,可以为一个类或结构体定义多个构造函数,每个构造函数都有自己独特的签名和行为。这些构造函数可以采取不同的形式,例如
- 默认构造函数
- 复制构造函数
- 移动构造函数
以及更多,这些将在课程后期介绍。C++ 中的对象构造是一个广泛的话题,有许多高级特性和技术。在本课程中,我们将只介绍构造函数的基础知识以及它们如何用于控制对象的初始化。
根据上下文和对象的构造方式,将调用特定的构造函数。这允许对对象的初始化具有更大的灵活性和控制。
现在,让我们从最简单的构造函数形式开始。
默认构造函数
C++ 中的默认构造函数是可以不带任何参数调用的构造函数。当没有定义其他构造函数时,它由编译器自动提供*
,但它也可以显式定义。例如,下面的 `Person` 结构体有一个默认构造函数
struct Person {
std::string name;
int age;
// Default settings
Person() {
name = "John Doe";
age = 18;
}
};
它也可以只在结构体内部声明,然后在结构体外部定义,就像常规方法一样。例如
struct Person {
std::string name;
int age;
Person(); // declaration only
};
// definition
Person::Person() {
name = "John Doe";
age = 18;
}
请注意,在前面的 `Person` 结构体示例中,数据成员可以轻松地在**不**手动编写构造函数的情况下初始化。在前面的课程中,我们已经看到可以使用赋值运算符代替数据成员声明,作为一种速记符号
struct Person {
std::string name = "John Doe";
int age = 18;
};
这是因为在这种情况下,编译器会自动为我们生成一个合适的构造函数,但在这节课中,我们想演示我们可以手动编写它,并可能添加额外的逻辑,就像最开始的例子一样。编写自定义默认构造函数(或一般构造函数)的能力使我们能够更好地控制对象的构造和初始化方式,并有助于确保对象以有效状态创建。
通常来说,你**只**应该在需要添加一些额外逻辑,或者想要对对象的数据成员强制执行一些约束时才编写构造函数。请参阅示例以更好地了解何时使用它们。
参数化构造函数
参数化构造函数是接受一个或多个参数的构造函数。这允许在对象的初始化中具有更大的灵活性。我们在本课程开头的例子中使用了它,以强制传递给构造函数的 `health` 值在 `0` 和 `maxHealth` 值之间。
要使用参数化构造函数实例化对象,我们需要将所需的参数传递给构造函数,像这样
// prism-push-types:Player
Player player(100, 50); // maxHealth = 100, health = 50
被删除的默认构造函数
如果只提供一个参数化构造函数,**编译器将删除**默认构造函数。我们之前的代码就是这种情况。尝试在不传递任何参数的情况下创建 `Player` 对象将导致编译器错误
// prism-push-types:Player
Player player; // error: no matching function for call to 'Player::Player()'
要恢复默认构造函数,可以使用 `default` 关键字,如下所示
struct Player {
// <data members>
Player(int maxHp, int hp) {
// ...
}
Player() = default; // enforce compiler to create a default constructor
};
复制构造函数
声明一个带有与结构体相同类型的单个参数的构造函数是不允许的
// prism-push-types:Person
Person(Person other) { // error
// ...
}