C++类与对象基础
目录
1.取地址运算符重载
2.初始化列表
3.类型转换
既前面所讲的C++类与对象知识,C++类与对象——基础知识-CSDN博客
C++类与对象——构造函数与析构函数-CSDN博客
C++类与对象——拷贝构造与运算符重载_c++拷贝对象和对象调用同一函数的输出区别怎么实现-CSDN博客本章我们将继续学习类与对象的基础知识。
首先是最后的两个默认成员函数:取地址运算符重载和const取地址运算符重载
1.取地址运算符重载
在这之前,我们先看一下const的知识。
const修饰的成员函数叫做const成员函数,const放到成员函数列表的后面.
用const修饰是因为有时候会用到const对象,比如下面的例子
d调用Print()函数没错,而d1调用Pritn()函数就报错了,这是因为我们前面说过this指针,Print()函数会传一个参数指向这个对象的指针this,类型是 Date* const this。const修饰this,表示this指向不能改,但this指向的内容是可以修改的,因为d1有const修饰,所以调用时传递的参数类型是const Date* const this。实参传到形参权限放大了,所以报错.权限只能够缩小,不能够放大..所以要让形参也是const类型,又因为this指针是不显示写的,所以无法在括号内加const,就在括号外加const,即是:
这样两个都不会报错了,因为权限是可以缩小的。
加了const的函数也叫常函数,普通对象和常对象都可以调用常函数,常对象只能调用常函数,不能调用普通函数。原因还是权限只能缩小,不能放大。
接下来进入正题。取地址运算符重载。
可以看到成功的取出了d和d1的地址,可是运算符只对内置类型重载了,Date是自定义类型啊,所以这是因为编译器自动生成了两个取地址重载函数,大概就是下面的样子:
要注意const函数和普通函数也是构成重载的,毕竟它们形参类型不同,一个是Date* const this.
一个是const Date* const this。因为用了const修饰,所以返回值也是const Date*.
一般这两个都不需要我们重写,默认的就够用了。如果你不想别人获得地址时可以在写一个。比如:
2.初始化列表
在之前的构造函数那里我们初始化主要是在函数体内部实现,但构造函数初始化还有一种方式,那就是初始化列表。
初始化列表在语法上可以理解为每个成员变量定义初始化的地方,每个成员变量在初始化列表中只能初始化一次。
要注意:引用成员变量,const成员变量,没有默认构造的自定义类型成员变量这三个必须要走初始化列表。
首先引用和const我们知道是必须在声明的位置初始化的。所以必须走初始化列表。 而没有默认构造的自定义类型成员变量即构造函数写了且是有参构造函数。因为声明时就实例化了,要走默认构造函数,没有默认构造就会报错,所以要走初始化列表。
C++11支持在变量声明的位置给缺省值,这个缺省值是给没有在初始化列表中显示初始化的成员变量使用的,
总结一下就是:
无论写没写初始化列表,每个构造函数都有初始化列表。无论是否在初始化列表中显示初始化成员变量,每个成员变量都要走初始化列表初始化。
还要注意一点,就是:初始化列表中初始化的顺序是声明的顺序,不是在初始化列表中的顺序。
所以_a1是1,而_a2是随机值。首先它们都是显示初始化了,所以就与缺省值无关了,不用看缺省值,因为_a2先声明,所以先初始化,用_a1来初始化,这时候_a1还是随机值,然后才是_a1初始化为1.
3.类型转换
C++支持内置类型隐式转换为类类型对象,但需要有相关内置类型为参数的构造函数。
成功运行,没有问题,
A aa = 1;
这一句代码实际上是先用1构造了一个临时对象,再把这个临时对象通过拷贝构造赋值给aa。所以实际上是两个过程,但VS2022上显示的只有一个构造的过程,这是因为编译器进行了优化,优化为了直接构造。
-fno-elide-constructors
在g++编译时加上上面的代码就可以关闭优化,从而看到具体的过程,可以自己去实践一下。
所以c可以引用一个整型,但是普通引用d就不行,因为1构造产生的临时对象具有常性,只能使用常引用。
使用这样的隐式类型转换可以方便我们传参。
多参数的隐式类型转换也是可以的,这是C++11新支持的语法。
同样的多参数隐式类型转换也可以用于传参。
不仅内置类型可以转化为类,类与类之间也可以隐式类型转换,只要有对应的构造函数就行了。
如果想要不支持隐式类型转换的话,可以在构造函数前面加上一个 explicit 关键字。
这就是本节的全部内容了,我们下一节再见!