文章目录
- this指针
- this指针的定义
- this指针的“工作”原理
- this指针的作用
- this指针的特点
- 构造函数
- 构造函数的定义
- 构造函数的作用
- 构造函数的特点
- 构造函数的调用方式
- 括号法
- 无参构造或者全缺省构造
- 需要传参才能调用的构造函数
- 隐式类型转换法
- 是只传一个参数就能调用的构造函数
- 是要传多个参数才能调用的构造函数
- 成员初始化列表
- 成员初始化列表的位置和语法
- 成员初始化列表的特点
- 总结
this指针
this指针的定义
C++编译器给每个
非静态的成员函数
增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),这个指针就是this指针
在函数体中所有“成员变量”的操作,都是通过该指针去访问。
只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成
this指针的“工作”原理
任何一个对象调用成员函数的时候
编译器都会隐式地
把这个对象的地址也作为参数传递给成员函数,在成员函数的参数表中也隐藏着一个形参this,这个this就接收了编译器传递的调用成员函数的对象的地址
类似下图
只不过上述过程都由编译器自己完成,而且是隐式地完成
程序员看不见,也不能
由程序员主动完成,会报错
this指针的作用
通过我的上一篇文章我们能知道:成员函数不是存储在对象中,而是存放在公共代码区
但是任何一个类实例化出的对象都能调用该类的成员函数,那么成员函数如何知道是哪一个对象在调用它呢?
-
通过this指针就可以知道是哪一个对象在调用成员函数了,因为this指针指向了调用这个成员函数的对象
-
this指针是
const修饰
的指针,指向了调用成员函数的对象,那么this指针除了不能改变指向
以外,所有的指针操作它都可以使用【例如 解引用,以及通过操作符 -> 使用对象的成员】 -
this指针可以区分成员函数中与对象的成员变量
同名的
变量,即this指针指向的
那一个是成员变量
例
this指针的特点
-
this指针的类型:类 类型*
const
,即成员函数中,不能
改变this指针的指向 -
this指针本质上是“成员函数”的
形参
,当对象调用成员函数时,编译器
将对象地址作为实参传递给
this形参【程序员不能显示传递】。所以对象中不存储
this指针。 -
只能在“成员函数”的
内部
使用,因为this指针是形参
,出了成员函数作用域就销毁了
构造函数
构造函数的定义
在创建对象时调用的特殊方法。其
主要作用是给对象的成员赋值
。
在C++中,构造函数通常没有返回类型
,并且不能被声明为const
。
在创建类的对象时,构造函数自动被调用
此外,构造函数可以重载,即可以有多个名字相同的构造函数,但参数列表必须不同。
构造函数的作用
主要作用:给存储在对象中
的成员变量赋初值
【注意:赋初值是赋值,不是初始化,初始化只能在定义时初始化一次,之后的改变成员的值都是赋值】
次要作用:由于构造函数是实例化对象时,编译器自动调用
可以根据这个特点,在构造函数中添加初始化以外的操作【例如记录一下调用了多少次构造函数等】,根据需求自定
构造函数的特点
-
实例化对象时,编译器
自动调用
对应构造函数 -
构造函数名
必须
与类名相同 -
构造函数
没有返回值
【void也不用写】 -
构造函数可以重载
例
-
构造函数
可以参数缺省
例
-
如果类中
没有显式定义
的构造函数,编译器会自动生成一个默认的构造函数【如果显式定义了
,就不会
有这个默认构造函数了】
编译器给的默认构造函数:
没有参数
对内置类型(int ,char等)一般
【有的编译器可能初始化成0】不做处理
【就是不初始化,让它还是随机值】
对自定义类型(类,结构体等)就调用它这个类型自己的默认构造
【默认构造 即不需要传参数
就可以调用的构造函数,例如无参构造和全缺省的构造函数】
例
C++11针对编译器给的默认构造内置类型不做处理的问题做出了一个优化:可以在类中内置类型声明时
给它缺省值
给了缺省值之后,编译器在调用构造函数之前
就会用缺省值给内置类型的成员初始化
例
构造函数的调用方式
括号法
无参构造或者全缺省构造
调用无参构造或者全缺省构造直接实例化对象
就行
语法:类名 对象名
例
注意:
调用无参构造或者全缺省构造不要打空括号
因为
类名+标识符+()可以是一个返回值是类的对象的函数的声明
如果实例化对象的时无参构造也或者全缺省构造+()就区分不开
例
所以规定
调用无参构造或者全缺省构造不要打空括号
需要传参才能调用的构造函数
语法; 类名 + 对象名+(参数表)
例
隐式类型转换法
是只传一个参数就能调用的构造函数
语法:== 类名 + 对象名 = 参数==
【参数的类型必须与构造函数的形参类型一致
】
例
是要传多个参数才能调用的构造函数
语法: 类名 + 对象名 = {参数1,参数2,………}
【参数的类型必须与构造函数的形参类型一致
】
例
原理:
语法上:
编译器使用 赋值操作符(=)的右操作数调用了构造函数构造出了一个临时对象
,再用这个临时对象拷贝构造
出了目标对象
实际上:
编译器会在语法实现上做出优化
:
直接使用赋值操作符(=)的右操作数调用了构造函数构造出了目标对象
成员初始化列表
如果说类里写的是成员的声明,那么成员初始化列表就是成员定义
和初始化
的地方
成员初始化列表的位置和语法
构造函数实现的()之后,构造函数的函数体之前
语法:
:+成员名+(要初始化成的东西),成员名+(要初始化成的东西)………
例
成员初始化列表的特点
-
成员初始化列表中只初始化
存储在对象中
的成员 -
每个成员
只能
在成员初始化列表中出现一次
【成员初始化列表就是成员定义
和初始化
的地方==,因为初始化只能初始化一次】
例
-
成员初始化列表初始化的顺序
不是
在成员初始化列表中成员变量出现的顺序
成员变量在类中声明的顺序
才是成员初始化列表初始化的顺序
例
-
其他自定义类型的对象成员变量
的默认构造
是在成员初始化列表中调用的【无论成员初始化列表中有没有写都会调用】 -
以下成员变量必须在成员初始化列表中初始化
1 引用成员变量【因为引用必须初始化】
2const
修饰的成员变量【因为被const修饰之后就不能被改变了,所以只能在初始化的时候赋初值】
3 其他自定义类型且没有默认构造
的对象【因为没有默认构造,编译器就不能自动调用构造函数了,而给构造函数传参只能在定义初始化时传递
】 -
类中声明的成员变量的
缺省值
其实是传给成员初始化列表的,因为是缺省值,所以如果对应成员变量在成员初始化列表中已经有值了,就不会再用缺省值了
例
总结
综上:成员初始化列表比构造函数更有优势
所以赋初值尽量使用成员初始化列表
以上就是本篇文章的全部内容了,如果对你有帮助的话,可以点赞收藏支持一下吗