C++:默认成员函数和this指针
类的六个默认成员函数
在学习这些默认的成员函数之前,务必先来了解一下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指针相关推荐
- 一文带你入门C++,类与对象、6个默认成员函数、this指针以及static关键字。
C++98关键字:63个 一.命名空间规则(namespace) 1.命名空间可以解决函数.全局变量名重复的问题,包在不同的命名空间里的重复函数,实际就是两个完全无关的函数. 2.命名空间允许续嵌套: ...
- C++>继承,继承方式及其比较,子类和父类对象指针,派生类的默认成员函数,虚继承,继承与友元,继承与静态成员
继承 继承的概念与定义 概念: 继承是指一个子类(或称为派生类)继承父类(或称为基类)的特征(属性和操作).继承是面向对象程序设计时实现代码复用的重要手段,它允许在原有的类的基础上进行扩展,增加功能, ...
- c 类别构造函数需要包含所有成员吗_C++默认成员函数解析
1.什么是面向对象? 概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法. 对象指的是类的实例,将对象作为程序的基本单元,将程 ...
- 3_V1-类和对象 -- 默认成员函数
定义一个日期类 #include <iostream> #include <assert.h> using namespace std;class Date { public: ...
- 类的6个默认成员函数:构造函数、析构函数、拷贝构造函数、重载运算符、三/五法则
文章目录 6个默认成员函数 构造函数 概念 默认构造函数的类型 默认实参 概念 默认实参的使用 默认实参声明 全局变量作为默认实参 某些类不能依赖于编译器合成的默认构造函数 第一个原因 第二个原因 第 ...
- 【C++】默认成员函数
前言 一.什么是默认成员函数 二.构造函数 三.析构函数 四.拷贝构造 五.赋值运算符重载 六.const成员 七.&运算符重载(了解) 总结: 前言 这一节主要讲四个默认成员函数.运算符重载 ...
- 【C++从入门到踹门】第三篇:类和对象(中)类的默认成员函数
目录 1.类的默认成员函数 2.构造函数 2.1 构造函数引入 2.2 构造函数概念及特点 3. 析构函数 3.1 析构函数引入 3.2 析构函数的概念 3.3 在哪些情况下会程序会执行析构函数? 3 ...
- 【C++】类和对象【中篇】--C++六个默认成员函数以及const成员函数
文章目录 一.类的6个默认成员函数 二.构造函数 1.概念 2.特性 2.1特征分析--自动生成 2.2.特征分析--选择处理 2.3特征分析--默认构造 3.C++11补丁--缺省值 三.析构函数 ...
- C++空类的默认成员函数总结
C++空类的默认成员函数总结 做IT就要做精英,至少4000/月吧? JAVAV工程师权威认证 [上海央邦]学一送一,超值![安博亚威]CCIE考试通过率第一! 定向委培RHCA,通过考试年薪10W ...
最新文章
- Python添加邮件附件并通过邮件发送测试报告
- 判断一个数是否是2的平方
- lr不能直接转ps编辑_摄影后期调色软件,Lr软件包
- 用php写弧度转角度,Python中转换角度为弧度的radians()方法
- 人脸关键点标注工具_谈谈人脸关键点的江湖
- 【推荐精读】从item-base到svd再到rbm,多种Collaborative Filtering(协同过滤算法)从原理到实现
- 这个“猫窝”太豪华?硅谷宠物猫住1500美元公寓
- 刘铁猛-深入浅出WPF-系列资源汇总
- gm220s路由器怎么设置_中国移动GM220-S光猫修改为桥接模式并启用IPV6
- 安卓防盗软件_Android勒索软件分析
- Java设计模式:简单工厂模式(附实例代码)每天一学设计模式
- rup 裁剪_小型软件项目RUP裁剪模型的研究
- 基于QT的IM(jabber)库和客户端
- springboot+pagehelper踩坑,PageHelper.startPage没有生效问题
- java指定小数点位数_Java指定保留小数位数的方法
- 【学习—Scrapy1】日常操作
- PAT A1008 Elevator (20 分)
- Sources for ‘Android API 32 Platform’ not found
- Ubuntu换源操作+vim的下载
- python爬取QQ音乐免费歌曲 2020.7.26