第九章:C++构造函数和析构函数详解

简介: 第九章:C++构造函数和析构函数详解

第九章:C++构造函数和析构函数详解

1. 概述

在C++中,构造函数和析构函数是用于初始化对象和清理对象资源的特殊成员函数。构造函数负责完成对象的初始化工作,而析构函数则负责在对象生命周期结束时清理资源。

2. 构造函数

构造函数是一种特殊的成员函数,与类名相同且没有返回类型。它在创建对象时被自动调用,用于执行必要的初始化操作

2.1 构造函数的定义

每个类可以有一个或多个构造函数。根据参数列表的不同,构造函数可以分为无参构造函数和有参构造函数。

class MyClass {
public:
    // 无参构造函数
    MyClass() {
        // 初始化代码
    }
    // 有参构造函数
    MyClass(int value) {
        // 初始化代码
    }
};

2.2 构造函数的调用

构造函数在创建对象时被自动调用,不需要显式调用构造函数。当创建对象时,编译器会根据提供的参数匹配合适的构造函数进行调用。

MyClass obj1;           // 调用无参构造函数创建对象
MyClass obj2(100);      // 调用有参构造函数创建对象

2.3 初始化列表

构造函数的初始化列表可以用于对成员变量进行初始化。使用初始化列表可以提供更高效的初始化方法,并确保成员变量按正确的顺序初始化。

class MyClass {
private:
    int value;
    double scale;
public:
    MyClass(int v, double s) : value(v), scale(s) {
        // 初始化代码
    }
};

2.4 默认构造函数

如果没有为类定义任何构造函数,编译器会自动生成一个默认构造函数。默认构造函数不接受任何参数,也不执行任何初始化操作。但一旦自定义了其他构造函数,编译器将不再生成默认构造函数。

class MyClass {
public:
    // 自定义构造函数
    MyClass(int value) {
        // 初始化代码
    }
    // 编译器不会生成默认构造函数
};

2.5 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,用于创建一个新对象并使用已有对象进行初始化。它可以通过值传递或引用传递来调用。

class MyClass {
public:
    // 拷贝构造函数
    MyClass(const MyClass& other) {
        // 初始化代码,使用other对象的值来初始化新的对象
    }
};
MyClass obj1;           // 调用无参构造函数创建对象obj1
MyClass obj2(obj1);     // 调用拷贝构造函数创建对象obj2,使用obj1的值来初始化

3. 析构函数

析构函数是一种特殊的成员函数,与类名相同但在前面加上波浪号(~)。它用于释放对象占用的资源。

3.1 析构函数的定义

每个类只能有一个析构函数,没有返回类型,也不接受任何参数。

class MyClass {
public:
    // 析构函数
    ~MyClass() {
        // 清理资源的代码
    }
};

3.2 析构函数的调用

析构函数在对象被销毁时自动调用,无法手动显式调用。当对象超过其作用域、删除对象的指针或程序结束时,析构函数会被调用。

void Function() {
    MyClass obj;    // 对象obj在该函数块结束时将被销毁,自动调用析构函数
}
int main() {
    MyClass* ptr = new MyClass();   // 使用new动态创建对象,需要手动delete释放内存
    delete ptr;                     // 调用析构函数后释放内存
    return 0;
}

3.3 析构函数的应用

析构函数经常用于释放对象占用的资源,如内存、文件句柄、网络连接等。通过在析构函数中执行必要的清理操作,可以避免资源泄漏。

class FileManager {
private:
    FILE* file;
public:
    FileManager(const char* filename) {
        file = fopen(filename, "r");   // 打开文件
        if (!file) {
            // 处理打开文件失败的情况
        }
    }
    ~FileManager() {
        if (file) {
            fclose(file);   // 关闭文件
        }
    }
};

4. 示例案例:图书管理系统

下面是一个简单的图书管理系统示例,用于展示构造函数和析构函数的实际应用。

#include <iostream>
#include <vector>
using namespace std;
// Book类表示图书对象
class Book {
private:
    string title;
    string author;
public:
    Book(const string& t, const string& a) : title(t), author(a) {
        cout << "Book \"" << title << "\" by " << author << " created." << endl;
    }
    ~Book() {
        cout << "Book \"" << title << "\" by " << author << " destroyed." << endl;
    }
    void display() {
        cout << "Title: " << title << endl;
        cout << "Author: " << author << endl;
    }
};
// Library类表示图书馆
class Library {
private:
    vector<Book> books;
public:
    void addBook(const Book& book) {
        books.push_back(book);
    }
    void displayAllBooks() {
        for (const auto& book : books) {
            book.display();
            cout << endl;
        }
    }
};
int main() {
    Library library;
    library.addBook(Book("Harry Potter", "J.K. Rowling"));
    library.addBook(Book("To Kill a Mockingbird", "Harper Lee"));
    library.displayAllBooks();
    return 0;
}

运行结果:

Book "Harry Potter" by J.K. Rowling created.
Book "To Kill a Mockingbird" by Harper Lee created.
Title: Harry Potter
Author: J.K. Rowling
Title: To Kill a Mockingbird
Author: Harper Lee
Book "Harry Potter" by J.K. Rowling destroyed.
Book "To Kill a Mockingbird" by Harper Lee destroyed.

运行以上示例代码,我们可以看到构造函数和析构函数的调用情况。在创建图书对象时,构造函数被调用,初始化了对象的成员变量,并输出了相应的提示信息。而当程序结束时,或者从图书馆中删除图书对象时,析构函数会被调用,释放了对象占用的资源,并输出了相应的销毁信息。

相关文章
|
27天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
70 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
72 4
|
3月前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
77 30
|
2月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
24 1
|
2月前
|
C++
C++构造函数初始化类对象
C++构造函数初始化类对象
22 0
|
2月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
26 0
|
4月前
|
编译器 C++
C++的基类和派生类构造函数
基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:
|
5月前
|
C++ 运维
开发与运维函数问题之析构函数在C++类中起什么作用如何解决
开发与运维函数问题之析构函数在C++类中起什么作用如何解决
44 11
|
5月前
|
编译器 C++
【C++】详解构造函数
【C++】详解构造函数
|
6月前
|
存储 编译器 C++
【C++】类和对象④(再谈构造函数:初始化列表,隐式类型转换,缺省值
C++中的隐式类型转换在变量赋值和函数调用中常见,如`double`转`int`。取引用时,须用`const`以防修改临时变量,如`const int& b = a;`。类可以有隐式单参构造,使`A aa2 = 1;`合法,但`explicit`关键字可阻止这种转换。C++11起,成员变量可设默认值,如`int _b1 = 1;`。博客探讨构造函数、初始化列表及编译器优化,关注更多C++特性。