类的六个默认成员函数

类中,默认生成六个成员函数:

  • 构造函数
  • 拷贝构造函数
  • 析构函数
  • 赋值运算符重载
  • 取地址(&)运算符重载
  • const修饰的取地址运算符重载

构造函数

 class Date
 {
 public:
     Date()
     {
         _year = 0; 
         _month = 0; 
         _day = 0;
     }
 private:
     int _year;
     int _month;
     int _day;
 };

构造函数是一个特殊的成员函数,是在创造类类型对象,对象被实例化时,由编译器自动调用。
构造函数名字与类名相同,不能由用户自主命名,没有类型,没有返回值。
在对象的生命周期内只且只调用一次,以保证每个数据成员都有一个合适的初始值。它不能被用户调用,且没有this指针。
构造函数有初始化列表,可以进行初始化也可以不进行。
构造函数功能是由用户自己定义的,用户根据初始化的要求设计函数体和函数参数。
用户如果没有自己定义构造函数,则系统会自动生成一个空的默认构造函数,不执行任何操作,但是仍然会被调用。

初始化列表

除了在函数体内初始化的方式之外,还可以在函数首部,通过初始化列表对数据成员实现初始化。
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。

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

为何会有这种方法?
有些数据成员,例如用const修饰的变量必须在创建的时候进行初始化,所以只能通过初始化列表进行初始化,而且这种方法比较高效。

带参构造函数

在定义对象时,希望给不同的对象赋予不同的初始值。

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

 int main()
 {
     Date d1(2017, 3, 19);
     Date d2(1970, 1, 1);
     system("pause");
     return 0;
 }

构造函数重载

类中可以包含多个构造函数,即构造函数可重载。
在建立类对象时,只执行其中一个构造函数。


  1. 最好在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。
  2. 在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数。
  3. 无参合全缺省构造函数均为缺省构造函数。
  4. 构造函数不能用const修饰,一旦使用const修饰,则不能给成员赋值,失去意义。
  5. 构造函数其实是有返回值的,返回this指针。
  6. 用explicit修饰构造函数,抑制由构造函数定义的隐式类型转
    换。
    explicit关键字需要放置在类中构造函数的声明上,在类外构造函数的定义体中不需要再写。

拷贝构造函数

拷贝构造函数就是由一个已有的对象复制出多个完全相同的对象。是构造函数的重载。
拷贝构造函数只有单个形参,而且该形参是对本类类型对象的引用(常用
const修饰)。
拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进
行初始化,由编译器自动调用。

 class Date
 {
 public:
     Date(int year, int month, int day)
         : _year(year)
         , _month(month)
         ,_day(day)
     {
     }
     Date(const Date& d)
     {
         _year = d.year;
         _month = d.month;
         _day = d.day;
     }
 private:
     int _year;
     int _month;
     int _day;
 };

拷贝构造函数必须使用同类型对象的引用传递,为什么呢?
如果不是引用的话,会引发无穷的递归。

什么时候用拷贝构造函数

当程序中需要建立一个新的对象,而这个新的对象是用另一个对象初始化它。

Date d1(2017, 3, 19);
Date d2(d1);

当函数的参数是类的对象时。在调用函数时需将实参对象完整地传递给形参,也就是需要建立一个实参的拷贝。

 void test(const Date d)
 {
 }

当函数的返回值是类的对象时。函数调用完毕将返回值带回时,需要将函数中的对象拷贝一个临时对象返回。

Date test()
{
    Date d;
    return d;
}

析构函数

析构函数的作用与构造函数相反。定义格式为在类名前面加上取反(~)符号。
析构函数无参数无返回值。在对象释放前调用。
未定义析构函数则系统会自动生成缺省的析构函数。

1、析构函数的作用并不是删除对象,而是在撤销对象时做一些清理工作。比如关闭打开的文件,释放开辟的动态内存等工作。
2、析构函数不返回任何值,没有函数类型,没有参数,因此也不能重载。
3、调用构造函数和析构函数的顺序:
因为函数压栈的关系,所以先构造的后析构,后构造的先析构。如果有全局对象或者静态局部对象,则它们在main函数结束或者调用exit函数时2被析构。

赋值运算符重载

同一类中的两个或多个对象之间可以相互赋值,即一个对象中的所有数据成员可以赋予另一个同类的对象。这时赋值运算符普通的功能已经无法满足使用,因此便有了赋值运算符的重载。
对象之间的重载也是通过赋值运算符“=”来实现。
赋值运算符重载和拷贝构造函数功能不同,赋值运算符时对一个已经创建的对象赋值。
使用赋值运算符时,类的数据成员中不能包括动态分配的数据。否则在析构时会将同一块内存释放多次。

 class Date
 {
 public:
     Date(int year, int month, int day)
         : _year(year)
         , _month(month)
         ,_day(day)
     {
     }
     Date operator=(Date& d)
     {
         _year = d._year;
         _month = d._month;
         _day = d._day;
     }
 private:
     int _year;
     int _month;
     int _day;
 };

取地址(&)运算符重载

const修饰的取地址运算符重载

 class Date
 {
 public:
     Date(int year, int month, int day)
         : _year(year)
         , _month(month)
         ,_day(day)
     {
     }
     const Date* operator&()const
     {
         return this;
     }
 private:
     int _year;
     int _month;
     int _day;
 };
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值