目录
  • 类的默认成员函数
  • 构造函数
    • 概念
    • 特性
  • 析构函数
    • 概念
    • 特性
  • 拷贝构造函数
    • 概念
    • 特征
  • 赋值运算符重载
    • 运算符重载
    • 赋值运算符重载
  • 取地址及const取地址操作符重载
    • 总结

      类的默认成员函数

      每个类中,如果不主动实现默写特定函数,类中也会自动去生成这些函数,它们就是默认成员函数。默认成员函数分为六种,它们是特殊的成员函数,如果我们不实现,编译器会自己实现。

      C++类与对象的详细说明2

      下面将对这些函数一 一进行介绍。

      构造函数

      概念

      构造函数的作用即为初始化,相当于平时我们自己写的Init函数,但在对象实例化时会自动调用,以保证实例化对象一定初始化。

      特性

      (1)函数名与类名相同

      如日期类Date,其构造函数名也为Date

      (2)无返回值

      以日期类为例,其构造函数的声明和定义可以写成如下样子:

      class Date{public:Date(int year = 0, int month = 1, int day = 1);private:int _year;int _month;int _day;};class Date
      {
      public:
      	Date(int year = 0, int month = 1, int day = 1);
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      Date::Date(int year, int month, int day)
      {
      	_year = year;
      	_month = month;
      	_day = day;
      }

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

      为了验证这一点,我们创建一个对象,但不对其进行其它操作:

      int main()
      {  
      	Date date1;
      	return 0;
      }

      C++类与对象的详细说明2

      C++类与对象的详细说明2

       通过调试可以发现对象date1已经被自动初始化了。

      (4)构造函数可以重载

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

      (6)无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

      针对第五点,我们不免会发出疑问,编译器自动生成的默认构造函数究竟干了什么呢?

      首先,需要先了解C++把类型分为两类:内置类型(基本类型)和自定义类型。

      内置类型就是C语言自带的类型,如int、char、double、指针、内置类型的数组;而自定义类型就是strucrt和class定义的类型。

      编译器默认生成的构造函数,对于成员变量中的内置类型不做初始化,对于自定义类型成员变量则会调用它的默认构造函数初始化,如果没有默认构造函数则会报错。

      析构函数

      概念

      析构函数的功能是完成对象中资源的清理。虚构函数会在对象的生命周期到了之后调用。

      特性

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

      (2)无参数无返回值。

      日期类析构函数的声明可以写成如下形式:

      ~Date();

      (3)一个类有且只有一个析构函数。若喂显式定义,系统会自动生成默认的析构函数。

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

      对于编译器自动生成的默认析构函数,与构造函数类似,对于内置类型成员变量不做处理;对于自定义类型成员变量会去调用它的构造函数。

      拷贝构造函数

      概念

      拷贝构造函数用于使用同类型对象去初始化实例对象。

      特征

      (1)拷贝构造函数是构造函数的一个重载形式。

      (2)拷贝构造函数的参数只有一个且必须使用引用传参,使用传值的方式会引发无穷递归调用。

      日期类拷贝构造函数的声明需要写成如下形式:

      Date(Date& date);

      为什么必须采用引用传参呢?引发无穷递归又是怎么一回事呢?

      不妨来思考一下,传参实际上也是对内容进行临时拷贝,将实参传给形参本身就需要调用拷贝构造。由此一来,会导致不断调用拷贝构造,造成无穷递归调用。

      (3)若未显式定义,系统会生成默认的拷贝构造函数了。

      默认拷贝构造函数对于内置类型成员,会完成按字节序的拷贝(浅拷贝),如果需要深拷贝则需要自己写拷贝构造函数;对于自定义类型成员,则会调用它的拷贝构造函数。

      所谓按字节序拷贝指将内存中的内容照搬照抄,复制过来。在一些情况下就会出错,如存放申请内存地址的指针,如果按字节序拷贝,会导致两个对象中的成员变量指向同一块空间,在析构时会导致同一块空间释放内存多次,引发错误。

      赋值运算符重载

      运算符重载

      在谈及赋值运算符重载前,必须先来讲一讲运算符重载。

      我们知道,对于int类型,是可以进行加减乘除等运算的。但对于自定义类型,能否实现加减乘除运算呢?这就需要运用到运算符重载了。

      运算符重载是具有特殊函数名的函数。函数名字为:operator操作符(参数列表)

      注意:一些运算符不支持重载,即:.*、::、sizeof、?:、.

      以Date类==运算符重载为例,需要将函数作为成员函数,以便于访问成员变量:

      class Date
      {
      public:
      	Date(int year = 0, int month = 1, int day = 1);
      	bool operator==(Date& date)const;
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      bool Date::operator==(Date& date)const
      {
      	return _year == date._year
      		&& _month == date._month
      		&& _day == date._day;
      }

      赋值运算符重载

      赋值运算符重载顾名思义,是对赋值运算符进行的重载,用于两个已经存在的对象进行赋值拷贝。

      赋值运算符重载有四个要点:

      (1)参数类型

      (2)返回值

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

      (4)返回*this,用于连续赋值

      一个类如果没有显式定义赋值运算符重载,编译器会自己生成一个,对于内置成员,完成按字节序拷贝;对于自定义成员变量,会调用它的赋值运算符重载。

      取地址及const取地址操作符重载

      这两个运算符一般不需要重新定义,使用编译器生成的重载即可,只有特殊情况才需要重载,如不希望自己特定的内容被别人访问时。

      总结

      篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容! 

      声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。