关于C++类的6个默认成员函数

一、总体介绍

        首先,当你定义出一个空类时(class  Date {}),你会觉得空类里面真的是空的吗?可当你进行一些使用时,如取地址,为什么还是可以正常使用呢?我猜你可能会说,因为这是C++默认就实现好了的啊,没错,在用户没有显式实现时,编译器会自动生成成员函数,这样的函数,称之为默认成员函数。那么既然如此,我们来看看成员函数有哪些,并如何显式实现:

        

 

二、初始化与清理(2个)

        1.构造函数

         构造函数主要完成的是初始化的工作,避免如C语言中使用某些变量时出现未初始化的警告和错误,显式的实现如下:

  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;
 };

调用如下:

                               

从上面的过程观察,可以发现以下几点特征:

                   (1). 函数名与类名相同
                   (2). 无返回值。  
                   (3). 对象实例化时编译器自动调用对应的构造函数。
                   (4). 构造函数可以重载。

         2.析构函数

           析构函数的功能与构造函数相反,在对象销毁时,对象会自动调用析构函数,完成对象中资源的清理,显式实现如下:

  class Date
 {
  public:
   ~Date()//析构函数
    {
        delete test;
        test=NULL:
	    _year = 0;
	    _month = 0;
	    _day = 0;
    }
  private:
      int _year;
      int _month;
      int _day;
      int* test;
 };

调用如下,不是很规范,看看即可:

                          

如此,从上可总结特征:

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

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

         (3). 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注                         意:析构函数不能重载
         (4). 对象生命周期结束时,C++编译系统系统自动调用析构函数

三、拷贝复制(2个)

        1. 拷贝构造函数

        既然这个函数有着构造的名字,那么差不多就和初始化有关,不过这个“初始化”是为了初始化一个与输入参数相同的类型出来,简单来说,就是copy。但要记住默认拷贝构造函数的浅拷贝只是简单的复制值,想要实现深拷贝,需要自己定义。显式实现如下:

class Date
{
  public:
    //Date(const Date d)//错误写法
    Date(const Date& d)//正确写法
    {
	    _year = d._year;
	    _month = d._month;
	    _day = d._day;
        int* _test=new int[10];
        memcpy(_test,d._test,10*sizeof(int);
    }
  private:
      int _year;
      int _month;
      int _day;
      int _test[10];
 };

调用如下:

                                          

如上观察,可以看到,拷贝构造函数是构造函数的一种重载,但也有一些特征,就是拷贝构造函数的参数有且只有一个,且必须是类 类型对象的引用,不然使用传值方式会引发无穷递归。

       发生无穷递归的原因说起来很简单,就是使用传值传参时,形参会去调用 ”拷贝构造函数“ 拷贝实参,然后就没了,就无穷递归下去了。听起来是不是挺懵逼的?hhhh,那么就举一个简单的说法,就是你要启动一个工具,但这个工具要首先调用另一个工具才能用,可是调用的工具又是都一样的,那么就无穷的调用下去了。

        2.赋值运算符重载

        该函数是C++为了增强代码的可读性而引入的,具有特殊的函数名和规则:           

            (1)不能通过连接其他符号来创建新的操作符:比如operator@
            (2)重载操作符必须有一个类类型参数
            (3)用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
            (4)作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参                        数为隐藏的this
            (5).* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
        可以看到上述规则有表明可以不在类中实现的意思,但是通常会在类中实现,不然为了获得类的私有成员变量时,要通过声明友元函数才能获得,下面看看该函数如何显式实现:
        
class Date
{
  public:

//等于=
Date& operator=(const Date& d)
{
	this->_year = d._year;
	this->_month = d._month;
	this->_day = d._day;

	return *this;
}

// 前置++
Date& operator++()
{
	*this+= 1;
	return *this;
}

 //后置++
Date operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

// 后置--
Date operator--(int)
{
	Date tmp(*this);
	*this-=1;
	return tmp;
}

// 前置--
Date& operator--()
{
	*this-=1;
	return *this;
}
  private:
      int _year;
      int _month;
      int _day;
      int _test[10];
 };

        调用如下:

                        

        观察上面过程,可以得出以下特征:

           (1)参数类型const T&,传递引用可以提高传参

           (2)返回值类型:一般使用T&,返回引用可以提高返回的效率,有返回值目的是为了支                         持连续赋值

          (3) 检测是否自己给自己赋值

          (4) 返回*this :保证可以连续赋值

三、取地址重载(2个)

        1&2.取地址操作符重载、const取地址操作符重载

        这两个函数其实差别不大,并且一般情况下编译器会自动生成,不用自己定义,除非想得到某些特定的内容才自己定义,显式实现如下:

class Date
{ 
public :

 Date* operator&()
 {
 return this ;
 }

 const Date* operator&()const
 {
 return this ;
 }

private :
 int _year ; // 年
 int _month ; // 月
 int _day ; // 日
};

调用如下:

                           

 四、总结

        这6个函数中前4个函数较为重要,一般使用时注意文中提到的点即可。但是为了本文的简洁可读性,有些细节问题没有去详细展开,如赋值运算符重载还细分为运算符重载,赋值运算符重载,若是各位还想继续了解,还需自行查找。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值