3.5 类的默认6个成员函数

        如果一个类中什么成员函数都没有,则称为空类,C++会自动生成6个默认成员函数,也称为缺省成员函数。

        6个默认成员函数分为3种,分别为:

                                                                1). 初始化和清理:构造函数、析构函数

                                                                2). 拷贝函数、赋值函数

                                                                3). 取地址重载

1.构造函数:用来保证对象一定被初始化的函数

        在C语言中我们经常用到结构体关键词struct,当我们用struct xxx 创建一个结构体变量时,这个结构体变量内部的一些参数往往是一些随机值,这些随机值如果我们忘记了初始化而直接使用,其结果是运行结果不对或程序报错。为了避免这件事的发生,在C++中引入了构造函数,它能够保证类中的一些变量会被初始化。

        那么如何编写一个构造函数呢?

        首先记住构造函数有如下特征:

                                                1).函数名与类名相同

                                                2).无返回值

                                                3).对象实例化时编译器自动调用对应的构造函数

                                                4).构造函数可以重载

      所谓的“对象实例化时编译器自动调用对应的构造函数”  是指你在类里面写了一个具体的构造函数代码,当你实例化(执行一个具体的值)时,系统会自动将你的实例形式与构造函数的形式比对,如果形式一致则将你实例中的具体参数值传给构造函数,经过构造函数给出结果。如果你的实例形式与构造函数的形式不一致,一般情况下系统会自动生成一个构造函数,给出相应的实例化结果。

class Date
{
public:
      // 1.无参构造函数
        Date()
        {}
     // 2.带参构造函数
        Date(int year, int month, int day)
        {
            _year = year;
            _month = month;
            _day = day;
        }
private:
        int _year;
        int _month;
        int _day;
};

void TestDate()
{
    Date d1; // 调用无参构造函数
    Date d2(2015, 1, 1); // 调用带参的构造函数

    // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
    // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
    // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
    Date d3();
}

        需要注意的是构造函数并不初始化内置类型成员,若还看见类中有内置类型成员被“赋值”这只是在给这个内置成员一个缺省值,并不是赋值,这是C++打的补丁。

2. 析构函数:当对象生命周期结束时,用来“清理善后”的函数。如释放内存等等

        在实际使用中,我们用到的变量都是有生命周期的,当变量生命周期结束时往往还要做一些打扫清理的工作,最简单的,用malloc给变量开辟一块空间,当这个变量使用结束并不再使用时,按道理来讲这时应该将这个变量指向的空间给释放掉,不然一直这样下去最终内存泄漏到一定量时系统会崩溃。为了防止这种情况的发生,C++建立了析构函数,对于上述的情况就可以将析构函数的内容写成释放内存的代码。这样当变量调用完毕时,系统自动执行析构函数时有析构函数可执行,自然系统内存就释放了。

        同理,如何编写一个析构函数呢?

        首先要记住析构函数的特征:

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

                                                2).无参数无返回值类型

                                                3).一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载

                                                4).对象生命周期结束时,C++编译系统系统自动调用析构函数

class Time
{
public:
        ~Time()
        {
            cout << "~Time()" << endl;
        }
private:
        int _hour;
        int _minute;
        int _second;
};
class Date
{
private:
        // 基本类型(内置类型)
        int _year = 1970;
        int _month = 1;
        int _day = 1;
        // 自定义类型
        Time _t;
};

int main()
{
    Date d;
    return 0;
}
// 程序运行结束后输出:~Time()
// 在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?
// 因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month, _day三个是
// 内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,所以在
// d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是:main函数
// 中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函
// 数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time
// 类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁
// main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数
// 注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数

        需要注意的是析构函数并不清理内置类型成员,系统会直接将其内存回收!

3. 拷贝构造函数:创建的实例化对象的对象名作为对象的参数

描述格式为:

一.原Data程序:
            Data(形参...)
        {
             1......
             2......
             3......
        }
二.拷贝构造函数实际使用格式:Data d2(d1),d1是Data类型

三.Data d2(d1)的原程序格式为Data (Data &d1):

            Data (Data &d1)
        {
            1......
            2......
            3......
        }
例子:

void func()
{
    Data d1(2022,9,25);
    Data d2(d1);//算拷贝成功
    Data d3 = d1;//也算拷贝成功(是为了兼容C)
}

        拷贝构造函数是构造函数的一个重载形式;拷贝构造函数的参数只有一个且必须是类型对象的引用,使用传值方式编译器直接存储,因为会引发无穷调用;在编译器默认生成的拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用拷贝构造函数完成拷贝的。

4. 运算符重载:创建一个函数,使自定义类型能够进行运算

一.运算符重载怎么使用:直接将两个类型变量放在一起进行加减乘除等运算就可以。

二.运算符重载源程序格式:类型 operator操作符(参数)
                
                  类型 operator操作符(参数1,参数2)
                {
                    ......
                }

//第一个参数代表左操作数,第二个参数代表右操作数
//一般operator操作符(参数1,参数2)里面的参数用const修饰,即引用传参的地方只要不改变尽量用const修饰
//当某些程序需要访问private下面的元素时,不妨把“某些程序”放进类里面,如果显示参数过多是因为类里的类型函数有this指针,多了一个参数,此时把之前的形参多的删除即可,this会默认对应第一个参数
//cout << (d1=d2) << endl 实际是 cout << operator=(d1,d2) << endl

5.取地址运算符重载

了解即可

class Date
    {
       public :
            Date* operator&()
        {
                return this ;
        }
            const Date* operator&()const
        {
                return this ;
        }
        private :
            int _year ; //年
            int _month ; //月
            int _day ; //日
    };

取地址运算符重载是默认成员函数,我们不写编译器自动生成,自动生成就够用了,一般不需要我们写;只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值