自学内容网 自学内容网

初谈构造函数和析构函数

加油学习的一天~~>_<~~

文章目录


前言

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并 不是开空间创建对象(我们常使⽤的局部对象是栈帧创建时,空间就开好了),⽽是对象实例化时初始化 对象。构造函数的本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数⾃动调⽤的 特点就完美的替代的了Init。

析构函数与构造函数功能相反,析构函数不是完成对对象本⾝的销毁,⽐如局部对象是存在栈帧的, 函数结束栈帧销毁,他就释放了,不需要我们管,C++规定对象在销毁时会⾃动调⽤析构函数,完成对 象中资源的清理释放⼯作。析构函数的功能类⽐我们之前Stack实现的Destroy功能,⽽像Date没有 Destroy,其实就是没有资源需要释放,所以严格说Date是不需要析构函数的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是构造函数?

(1)析构函数的特点:

1. 析构函数名是在类名前加上字符~。

2. ⽆参数⽆返回值。(这⾥跟构造类似,也不需要加void)

3. ⼀个类只能有⼀个析构函数。若未显式定义,系统会⾃动⽣成默认的析构函数。

4. 对象⽣命周期结束时,系统会⾃动调⽤析构函数。

5. 跟构造函数类似,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,⾃定类型成员会 调⽤他的析构函数。

6. 还需要注意的是我们显⽰写析构函数,对于⾃定义类型成员也会调⽤他的析构,也就是说⾃定义类 型成员⽆论什么情况都会⾃动调⽤析构函数

7. 如果类中没有申请资源时,析构函数可以不写,直接使⽤编译器⽣成的默认析构函数,如Date;如 果默认⽣成的析构就可以⽤,也就不需要显⽰写析构,如MyQueue;但是有资源申请时,⼀定要 ⾃⼰写析构,否则会造成资源泄漏,如Stack。

8. ⼀个局部域的多个对象,C++规定后定义的先析构。

(2)代码示例

#define MAX_STACK_SIZE 1000 
#include <iostream>
using namespace std;
typedef int STDataType;

class Stack
{
public :
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (nullptr == _a)
        {
            perror("申请失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }
    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _top = _capacity = 0;
    }

private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};//注意分号

//两个Stack实现队列
class Date
{
public:
    //无参构造函数
    Date()
    {
        _year = 1;
        _month = 1;
        _day = 1;
    }
    //带参构造函数
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;

    }

    //全缺省构造函数
    Date(int year=1, int month=1, int day=1)
    {
        _year = year;
        _month = month;
        _day = day;

    }
    void printf()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    // 如果留下三个构造中的第⼆个带参构造,第⼀个和第三个注释掉

        // 编译报错:error C2512 : “Date”:没有合适的默认构造函数可⽤
    // 调⽤默认构造函数
    Date d1;
    Date d2(2025, 1, 1);
        // 调⽤带参的构造函数

        //注意:如果通过⽆参构造函数创建对象时,对象后⾯不⽤跟括号,否则编译器⽆法

        // 区分这⾥是函数声明还是实例化对象

        // warning C4930: “Date d3(void)”: 未调⽤原型函数(是否是有意⽤变量定义的? )
    Date d3();
    d1.printf();
    d2.printf();
    return 0;
}

二、析构函数

(1)概念:

1. 析构函数名是在类名前加上字符~。

2. ⽆参数⽆返回值。(这⾥跟构造类似,也不需要加void)

3. ⼀个类只能有⼀个析构函数。若未显式定义,系统会⾃动⽣成默认的析构函数。

4. 对象⽣命周期结束时,系统会⾃动调⽤析构函数。

5. 跟构造函数类似,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,⾃定类型成员会 调⽤他的析构函数。

6. 还需要注意的是我们显⽰写析构函数,对于⾃定义类型成员也会调⽤他的析构,也就是说⾃定义类 型成员⽆论什么情况都会⾃动调⽤析构函数。 

7. 如果类中没有申请资源时,析构函数可以不写,直接使⽤编译器⽣成的默认析构函数,如Date;如 果默认⽣成的析构就可以⽤,也就不需要显⽰写析构,如MyQueue;但是有资源申请时,⼀定要 ⾃⼰写析构,否则会造成资源泄漏,如Stack。

8. ⼀个局部域的多个对象,C++规定后定义的先析构。

(2)代码如下(示例):

#define MAX_STACK_SIZE 1000 
#include <iostream>
using namespace std;
typedef int STDataType;

class Stack
{
public :
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (nullptr == _a)
        {
            perror("申请失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }
    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _top = _capacity = 0;
    }

private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};//注意分号

//两个Stack实现队列
class MYQueue
{
public:
//编译器默认⽣成MyQueue的析构函数调⽤了Stack的析构,释放的Stack内部的资源
// 显⽰写析构,也会⾃动调⽤Stack的析构
/*~MyQueue()
{}*/
private:
    Stack pushst;
    Stack popst;
};
int main()
{
    Stack st;
    MYQueue mq;

    return 0;
}


总结

析构函数和构造函数我也觉得特别难懂~~>_<~~


原文地址:https://blog.csdn.net/2302_80705024/article/details/142741161

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!