在 C++ 中,构造函数和析构函数是类的两个特殊的成员函数,它们与对象的生命周期紧密相关。
构造函数
构造函数是一种特殊的成员函数,用于在创建类的对象时初始化该对象。它的名称必须与类名完全相同,不能指定返回类型,即使是 void 也不行。以下是构造函数的一些特点:
-
初始化资源:构造函数负责分配对象使用的资源,如动态内存或打开文件。
-
自动调用:每次使用
new
表达式创建对象时,构造函数都会被自动调用。 -
重载:构造函数可以被重载,即一个类可以有多个构造函数,它们具有不同的参数列表。
-
默认构造函数:如果没有定义任何构造函数,编译器会提供一个默认的构造函数,它执行默认初始化。
-
初始化列表:构造函数使用初始化列表来高效地初始化成员变量和基类。
-
常量成员:构造函数是初始化常量成员的唯一地方。
析构函数
析构函数是与构造函数相对应,用于在对象生命周期结束时执行清理工作的成员函数。它的名称是 ~
紧跟着类名,同样不能有返回类型。以下是析构函数的一些特点:
-
释放资源:析构函数负责释放对象在构造时获得的资源,如动态分配的内存或关闭文件。
-
自动调用:当对象的生命周期结束时,析构函数会被自动调用。对于自动存储期对象,是在作用域结束时;对于动态分配的对象,是在
delete
表达式执行时。 -
不能重载:析构函数不能被重载,每个类只能有一个析构函数。
-
默认析构函数:如果没有定义析构函数,编译器会提供一个默认的析构函数,它执行默认的清理工作。
-
虚析构函数:在具有虚函数的类中,析构函数应该是虚的,以确保通过基类指针删除派生类对象时,正确的析构函数被调用。
-
不能抛出异常:析构函数不应该抛出异常,或者如果抛出异常,它必须能够保证资源被释放。
示例
class Example {
public:
// 构造函数
Example() {
std::cout << "Example constructed." << std::endl;
// 初始化工作
}
// 拷贝构造函数(一种特殊的构造函数)
Example(const Example& other) {
std::cout << "Copy constructed." << std::endl;
// 深拷贝资源
}
// 析构函数
~Example() {
std::cout << "Example destructed." << std::endl;
// 清理工作
}
// 成员函数
void doSomething() {
// ...
}
};
int main() {
Example obj; // 调用 Example 的构造函数
delete new Example(); // 调用 Example 的构造函数,然后调用析构函数
return 0;
}
在这个示例中,Example
类有两个构造函数和一个析构函数。程序的 main
函数中创建了一个 Example
对象和一个动态分配的 Example
对象。对于动态分配的对象,首先调用构造函数,然后调用 delete
时调用析构函数。对于自动存储期的对象,构造函数在进入 main
函数时调用,析构函数在离开 main
函数时调用。