第五节 · 亮相前的准备 · 类的构造函数

当我们创建一个对象时,它应该处于一个合理的初始状态。比如,一个 Counter 对象的计数值应该从 0 开始,一个 Person 对象应该有一个名字。

构造函数(Constructor)就是用来初始化对象的特殊成员函数。它在对象创建时自动调用,确保对象处于有效状态。


构造函数的基本形式

class Person
{
private:
    string name;
    int age;
    
public:
    // 构造函数:与类同名,没有返回类型
    Person()
    {
        name = "Unknown";
        age = 0;
        cout << "Person 对象被创建" << endl;
    }
};

int main()
{
    Person p;  // 自动调用构造函数
    // 输出: Person 对象被创建
    return 0;
}

构造函数的特点:

  • 与类同名

  • 没有返回类型(连 void 都没有)

  • 在对象创建时自动调用

  • 可以重载


带参数的构造函数


初始化列表

初始化成员变量的更好方式是使用初始化列表

初始化列表的优势:

  • 效率更高(直接初始化,而不是先默认初始化再赋值)

  • 某些成员必须用初始化列表初始化:

    • const 成员

    • 引用成员

    • 没有默认构造函数的类类型成员


默认构造函数

默认构造函数是不需要参数的构造函数。如果你没有定义任何构造函数,编译器会自动生成一个。

但如果你定义了任何构造函数,编译器就不会自动生成默认构造函数:

可以使用 = default 让编译器生成默认构造函数:


委托构造函数(C++11)

一个构造函数可以调用同类的另一个构造函数:


拷贝构造函数

拷贝构造函数用于创建一个对象的副本:

如果不定义,编译器会自动生成一个执行浅拷贝的拷贝构造函数。


析构函数

与构造函数相对的是析构函数(Destructor),它在对象销毁时自动调用:

析构函数的特点:

  • 名字是 ~ 加类名

  • 没有参数,没有返回类型

  • 每个类只能有一个析构函数

  • 不能重载


禁止拷贝

有时我们不希望对象被拷贝,可以删除拷贝构造函数和拷贝赋值运算符:


完整示例:银行账户


构造函数和析构函数是类的生命周期管理的核心。正确使用它们,可以确保资源的正确分配和释放,避免内存泄漏等问题。

习题

  • Rectangle 类编写构造函数,支持无参构造(默认 1x1)和带参构造。

  • 设计一个 Array 类,在构造函数中动态分配数组,在析构函数中释放。

  • 实现一个 Logger 类,在构造时打开日志文件,在析构时关闭。

Last updated