类的六个默认成员函数

在学习这些默认的成员函数之前,务必先来了解一下this指针,因为除了构造函数外其他的默认成员函数都有一个隐式的形参–this指针。这对于我们之后在默认成员函数的学习和使用方面有着很大的影响。
this指针

1、每个成员函数都有一个指针形参,他的名字是固定的,称为this指针,this指针是隐式的(构造函数没有this指针)。
2、编译器会对成员函数进行处理,在对象调用成员函数时,对象地址做实参传递给成员函数的第一个形参this指针。
3、this指针是成员函数的隐含的指针形参,是编译器自己处理的,我们不能再成员函数的形参中添加this指针的参数定义,也不能在调用时显示传递对象地址给this指针。
如图:编译器处理成员函数隐含的this指针:

需要注意一个问题,有时候也会被面试问到。
this指针是隐式的,不需要我们定义也不需要显式的传参,但他依旧是一个形参,因此this指针存在于栈上。

接下来我们主要学习以下4个默认成员函数。
1、构造函数
首先我们就有一个问题,在定义一个类时,我们通常会将成员变量定义为私有的,那么我们如何对这些私有的成员变量进行初始化呢???

//比如我们定义一个日期类
class Date
{
public:void Display(){cout<<year<<"-"<<month<<"-"<<day<<endl;}
private:int _year;int _month;int _day;
}
//我们看到这里的成员变量是私有的,如何初始化?
//这里我们就有了构造函数这一说

注意一点:构造函数是公有的,并且只在定义对象时自动执行一次
什么样的函数才叫构造函数呢??接下来看一下构造函数所具有的几大特征

1、函数名与类名相同
2、没有返回值
3、对象构造时系统自动调用对应的构造函数
4、构造函数可以重载
5、可以在类里面定义,也可以在类外面定义
6、若类中没有给出构造函数,则C++编译器会自动产生一个缺省的构造函数,但一旦我们定义了,系统就不会自动生成了。
7、无参的构造函数和全缺省的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个

代码展示:

class Date
{public://1.1:无参构造函数Date() //函数名与类名相同,没有返回值{_year = 1900;_month = 1;_day = 1;}//无参构造函数与全缺省的构造函数都是缺省构造函数,且只能存在一个。//1.2:全缺省的构造函数//Date(int year=1900,int month=1,int day=1)//{//    _year = year;//    _month = month;//    _day = day;//}//2:带参构造函数Date(int year,int month,int day)  //可构成函数重载{_year = year;_month = month;_day = day;}//1和2两个构造函数构成函数重载//函数重载:函数名相同,参数列表不同(参数个数,参数类型)//返回值可同可不同。void show(){cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}
private:int _year;int _month;int _day;
};
void Test()
{Date d1;//会调用无参构造函数Date d2(2018,7,31);//会调用有参构造函数
}

2、拷贝构造函数
我们有时候会遇到一种情况就是当我们实例化出一个新的对象时,想要用一个同类的对象对其进行初始化,这时我们就需要用到拷贝构造函数。

拷贝构造函数的特征:

1、拷贝构造函数其实就是构造函数的一个重载。
2、拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。
3、若为显式的定义,系统会默认缺省的拷贝构造函数,缺省的拷贝构造函数会依次拷贝类成员进行初始化。

代码展示:

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;
};
void Test()
{Date d1(2018,1,1);//以下两种方法等价Date d2(d1);Date d3=d1;
}


为什么拷贝构造函数必须使用引用传参?因为使用传值方式会引发无穷递归问题。
这里的无穷递归问题到底又是怎么一回事?

3、析构函数
我们知道构造函数是对象实例化时自动调用对应的构造函数,而当一个对象的生命周期结束时也会自动调用一个函数—析构函数。(其目的是为了做一些清理工作)
析构函数的几大特征:

1、函数名是在类名前加上~
2、没有参数没有返回值(包括void类型)
3、一个类有且只有一个析构函数(不能重载)
4、对象生命周期结束时,C++编译系统会自动调用析构函数
4、若类中没有给出析构函数,则C++编译器会自动产生一个缺省的析构函数(即使我们定义了,系统还是会自动生成一个,在调用时先调用用户自定义的在调用系统自动生成的)。

注意:因为我们说是在一个对象的生命周期结束的时候调用析构函数,就会想到说那么析构函数的作用就是把这个对象删掉。其实不是,析构函数并不会把一个生命周期已经结束的对象删除,只是做一些清理工作。
问题又来了,清理工作到底是什么???
代码展示:

class Array
{
public://有参构造函数Array(int n){_ptr = (int*)malloc(n*sizeof(int));}//析构函数~Array()//没有参数和返回值{if(_ptr){free(_ptr);//清理工作,也就是释放动态开辟的空间_ptr = NULL;}}
private:int *_ptr;
};

4、赋值运算符重载
为了增强程序的可读性,C++支持运算符的重载。
运算符重载特征:

1、operator+合法的运算符构成函数名(如:重载>运算符的函数名为 operator>)。
2、重载运算符后,不能改变运算符的优先级/结合性/操作数个数
3、.(成员访问运算符),.*(成员指针访问运算符),::(域运算符),?:(条件运算符),sizeof(长度运算符)。这五个运算符是不能被重载的。

赋值运算符的重载是对一个已经存在的对象进行拷贝赋值。
代码展示:

class Date
{
public://构造函数Date(){_year = 1900;_month = 1;_day = 1;}//拷贝构造函数Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//赋值运算符重载函数Date& operator= (const Date& d)//&是引用传参{if(this != &d)//&是取地址//这里的判断是为了防止自己给自己赋值的情况{this->_year = d._year;this->_month = d._month;this->_day = d._day;}return *this;}
private:int _year;int _month;int _day;
};

那么想一想,赋值运算符重载函数为什么返回值是 Date&呢???
看一下:

Date d1;
Date d3;
d3 = d1;//调用赋值运算符的重载
//走到这我们的d1已经赋给了d3
//试想。如果赋值运算符的重载返回的不是Date&,假设是void
//那么如果我们还想要将d3赋值给另外一个对象,一定是不行的
//因为在类型上都不匹配了,新实例化的对象是Date,而你在之前
//的赋值完成返回以后就把d3的类型改了,不再是Date类的对象了

所以说,之所以要返回Date&,是为了之后可以继续使用进行赋值。
另外需要注意的一点就是,拷贝构造的调用和赋值运算符重载的调用的区别。

Date d1;
//调用拷贝构造
Date d2 = d1;//此时d2还并不存在//调用赋值运算符的重载
Date d3;//d3已经被实例化出来
d3 = d1;//拷贝构造,顾名思义就是以拷贝的方式去构造出来,
//所以操作的对象是一个不存在的对象和一个已经存在的对象之间
//赋值是两个都已经存在的对象之间进行

C++:默认成员函数和this指针相关推荐

  1. 一文带你入门C++,类与对象、6个默认成员函数、this指针以及static关键字。

    C++98关键字:63个 一.命名空间规则(namespace) 1.命名空间可以解决函数.全局变量名重复的问题,包在不同的命名空间里的重复函数,实际就是两个完全无关的函数. 2.命名空间允许续嵌套: ...

  2. C++>继承,继承方式及其比较,子类和父类对象指针,派生类的默认成员函数,虚继承,继承与友元,继承与静态成员

    继承 继承的概念与定义 概念: 继承是指一个子类(或称为派生类)继承父类(或称为基类)的特征(属性和操作).继承是面向对象程序设计时实现代码复用的重要手段,它允许在原有的类的基础上进行扩展,增加功能, ...

  3. c 类别构造函数需要包含所有成员吗_C++默认成员函数解析

    1.什么是面向对象? 概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法. 对象指的是类的实例,将对象作为程序的基本单元,将程 ...

  4. 3_V1-类和对象 -- 默认成员函数

    定义一个日期类 #include <iostream> #include <assert.h> using namespace std;class Date { public: ...

  5. 类的6个默认成员函数:构造函数、析构函数、拷贝构造函数、重载运算符、三/五法则

    文章目录 6个默认成员函数 构造函数 概念 默认构造函数的类型 默认实参 概念 默认实参的使用 默认实参声明 全局变量作为默认实参 某些类不能依赖于编译器合成的默认构造函数 第一个原因 第二个原因 第 ...

  6. 【C++】默认成员函数

    前言 一.什么是默认成员函数 二.构造函数 三.析构函数 四.拷贝构造 五.赋值运算符重载 六.const成员 七.&运算符重载(了解) 总结: 前言 这一节主要讲四个默认成员函数.运算符重载 ...

  7. 【C++从入门到踹门】第三篇:类和对象(中)类的默认成员函数

    目录 1.类的默认成员函数 2.构造函数 2.1 构造函数引入 2.2 构造函数概念及特点 3. 析构函数 3.1 析构函数引入 3.2 析构函数的概念 3.3 在哪些情况下会程序会执行析构函数? 3 ...

  8. 【C++】类和对象【中篇】--C++六个默认成员函数以及const成员函数

    文章目录 一.类的6个默认成员函数 二.构造函数 1.概念 2.特性 2.1特征分析--自动生成 2.2.特征分析--选择处理 2.3特征分析--默认构造 3.C++11补丁--缺省值 三.析构函数 ...

  9. C++空类的默认成员函数总结

    C++空类的默认成员函数总结 做IT就要做精英,至少4000/月吧? JAVAV工程师权威认证 [上海央邦]学一送一,超值![安博亚威]CCIE考试通过率第一! 定向委培RHCA,通过考试年薪10W ...

最新文章

  1. Python添加邮件附件并通过邮件发送测试报告
  2. 判断一个数是否是2的平方
  3. lr不能直接转ps编辑_摄影后期调色软件,Lr软件包
  4. 用php写弧度转角度,Python中转换角度为弧度的radians()方法
  5. 人脸关键点标注工具_谈谈人脸关键点的江湖
  6. 【推荐精读】从item-base到svd再到rbm,多种Collaborative Filtering(协同过滤算法)从原理到实现
  7. 这个“猫窝”太豪华?硅谷宠物猫住1500美元公寓
  8. 刘铁猛-深入浅出WPF-系列资源汇总
  9. gm220s路由器怎么设置_中国移动GM220-S光猫修改为桥接模式并启用IPV6
  10. 安卓防盗软件_Android勒索软件分析
  11. Java设计模式:简单工厂模式(附实例代码)每天一学设计模式
  12. rup 裁剪_小型软件项目RUP裁剪模型的研究
  13. 基于QT的IM(jabber)库和客户端
  14. springboot+pagehelper踩坑,PageHelper.startPage没有生效问题
  15. java指定小数点位数_Java指定保留小数位数的方法
  16. 【学习—Scrapy1】日常操作
  17. PAT A1008 Elevator (20 分)
  18. Sources for ‘Android API 32 Platform’ not found
  19. Ubuntu换源操作+vim的下载
  20. python爬取QQ音乐免费歌曲 2020.7.26

热门文章

  1. kali linux中如何安装中文输入法
  2. 广电推出全新聚合广告联盟,为千万APP开发者带来福音。
  3. GFM(GitHub Flavored Markdown)与标准Markdown的语法区别
  4. GitHub支持的Markdown语法 GitHub Flavored Markdown
  5. 在线新华字典Sidebar Gadget
  6. Java面试流程及核心面试题
  7. 10 款国外实用、有趣的 GitHub 简介 README
  8. 动规(12)-开餐馆
  9. 576芯光缆交接箱SMC光交箱详细图文说明光缆交接箱SMC光交箱功能
  10. Java 字符串拆分