构造函数和析构函数

一、构造函数
1.什么是构造函数
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任 务并不是开空间创建对象,而是初始化对象。

2.特征
函数名与类名相同。
无返回值。(void 也不行)
对象实例化时编译器自动调用对应的构造函数。
构造函数可以重载。
class Date
{
public:
    //构造函数
    Date(int year ,int month , int day )
    {
        _year = year;
        _month = month;
        _day = day;
    }

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2023, 8, 12);
    d1.Print();

    
}


除了上面,也可以用多种构造函数,来完成初始化

class Date
{
public:
    //构造函数
    Date(int year ,int month , int day )
    {
        _year = year;
        _month = month;
        _day = day;
    }

    //无参构造函数
    Date()
    {
        _year = 2023;
        _month = 4;
        _day = 17;
    }

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2023, 8, 12);
    d1.Print();

    Date d2;
    d2.Print();
}


但是当这样写的时候,就会出现问题

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

    //无参构造函数
    Date()
    {
        _year = 2023;
        _month = 4;
        _day = 17;
    }

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2023, 8, 12);
    d1.Print();

    Date d2;
    d2.Print();

    
}

错误原因:对于不带参数的对象,既可以调用全缺省构造,也可以调用无参构造,但是编译器会不知道调用哪一个。

3.默认构造函数
如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

1、无参构造(没有形参的构造函数)称之为默认构造函数

2、全缺省构造(形参都有缺省值)也称之为默认构造函数

3、编译器自动生成的默认构造函数

对于编译器自己生成的,该类中的成员变量会被初始化为随机值

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

    无参构造函数
    //Date()
    //{
    //    _year = 2023;
    //    _month = 4;
    //    _day = 17;
    //}

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    /*Date d1(2023, 8, 12);
    d1.Print();*/

    Date d2;
    d2.Print();

    return 0;
}


关于编译器生成的默认成员函数,很多人会有疑惑:不实现构造函数的情况下,编译器会
生成默认的构造函数。但是看起来默认构造函数又没什么用?
对象调用了编译器生成的默认构造函数,但是对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用??
解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类
型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看
下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员
函数。

class Time
{
public:
    Time()
    {
        cout << "Time()" << endl;
        _hour = 0;
        _minute = 0;
        _second = 0;
    }
private:
    int _hour;
    int _minute;
    int _second;
};

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

    无参构造函数
    //Date()
    //{
    //    _year = 2023;
    //    _month = 4;
    //    _day = 17;
    //}

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    //内置类型
    int _year;
    int _month;
    int _day;

    //自定义类型
    Time _t;
};

int main()
{
    /*Date d1(2023, 8, 12);
    d1.Print();*/

    Date d2;
    d2.Print();

    return 0;
}

说明:_year,_month,_day都是随机值,而Time _t这个变量是class Time自定义类型,编译器会走到Time类中,调用该类的构造函数。

typedef int STDateType;
class Stack
{
public:
    Stack(size_t capacity = 4)
    {
        cout << "Stack()" << endl;
        _array = (STDateType*)malloc(sizeof(STDateType) * capacity);
        if (_array == nullptr)
        {
            perror("malloc fail");
            return;
        }
        _capacity = capacity;
        _size = 0;
    }

    void Push(STDateType x)
    {
        //CheckCapacity()
        _array[_size++] = x;
    }

    //析构函数
    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_array);
        _array = nullptr;
        _capacity = _size = 0;
    }
private:
    STDateType* _array;
    int _capacity;
    int _size;
};

class MyQueue
{
    Stack _pushST;
    Stack _popST;

};

int main()
{
    MyQueue q;
    return 0;
}


对于MyQueue来说,成员变量都为自定义类型,编译时会去调用Stack中的构造函数

二、析构函数
1.定义
析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

2.特性
析构函数名是在类名前加上字符 ~。
无参数无返回值类型。
一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构 函数不能重载。
对象生命周期结束时,C++编译系统系统自动调用析构函数。
typedef int STDateType;
class Stack
{
public:
    Stack(size_t capacity = 4)
    {
        cout << "Stack()" << endl;
        _array = (STDateType*)malloc(sizeof(STDateType) * capacity);
        if (_array == nullptr)
        {
            perror("malloc fail");
            return;
        }
        _capacity = capacity;
        _size = 0;
    }

    void Push(STDateType x)
    {
        //CheckCapacity()
        _array[_size++] = x;
    }

    //析构函数
    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_array);
        _array = nullptr;
        _capacity = _size = 0;
    }
private:
    STDateType* _array;
    int _capacity;
    int _size;
};

class MyQueue
{
    Stack _pushST;
    Stack _popST;

};

int main()
{
    Stack s;
    s.Push(1);

    return 0;
}


析构函数的调用是在执行return 0后,函数即将销毁时自动调用它,然后堆区空间就会被释放,且其他变量清零。

4.默认析构类型
默认析构函数与默认构造函数同理,都是我们不生成时,编译器自动生成一个析构函数,但编译器生成的也只能处理一些简单类型的成员变量,例如日期类:

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

    无参构造函数
    //Date()
    //{
    //    _year = 2023;
    //    _month = 4;
    //    _day = 17;
    //}

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    //内置类型
    int _year;
    int _month;
    int _day;

    //自定义类型
    Time _t;
};

int main()
{
    Date d1(2023, 8, 13);
    return 0;
}

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值