C++入门系列7:构造函数的三个作用
前言:C++入门系列文章,是按照鲍松山老师的C++入门课程进行的学习整理与记录,方便自己同时也方便一些编程新手,更好地去理解编程中许多概念和技术产生的原因,由来和发展过程,希望通过逻辑帮助自己更快也更长久地理解和应用。
尊重原创,因此先附上鲍老师的视频链接:https://edu.51cto.com/course/4940.html,感谢鲍老师的精心备课,悉心讲解与耐心传授。
1 构造函数
1.1 构造函数的三个作用?
构造函数的前2个作用应该是比较好理解的:
1:构造对象
2:初始化对象
我们还是先创建一个Test对象,该对象有一个私有变量:data
举例截图如上,我们创建了一个t1对象,默认参数为0,并且运行中自动调用了构造函数和析构函数。
接下来,我们在代码上在第28行加一行代码,t1 = 100,截图如下:
以上是断点调试到第30行是,我们看了一下t1对象的私有变量data的值为100.
好了,本节的第1个问题是,为什么可以把一个int 类型的变量100,赋值给一个Test对象t1呢?程序没有报错,而且成功地给t1对象的私有变量成员data赋值为100了。
1.2 类型转换的基本规则
要回答上面的问题,我们先来看一下C语言里面类型转换的基本规则。
由于C、C++、Java等都是强制类型定义的。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。
所以既然d是doudle类型的,那么为什么a可以成功地赋值为12呢?
那是因为发生了隐式转换,即编译器先把d强制类型转化为一个int类型的临时变量,值为12,然后由这个临时的int类型的变量去赋值给整型a。
所以强类型语言中不同类型之间不能直接赋值,必须先找到一个和被赋值变量类型一样的临时变量,再由该临时变量去赋值。
看到这里,1.1的问题是不是已经可以联想到了?
即是不是先把100隐式转成了一个Test类型的临时变量,然后再由该临时变量赋值给了t1,这样是不是就解释通了呢!
我们再完整地运行一遍以上代码:
由上图,在28行加了一句赋值语句后,是不是发现现在构造了2个对象了呢?这个多出来的对象就是我们刚刚分析的临时的Test对象。到这里,我们就解释了1.1中的问题了。
因此构造函数的3个作用如下:
1 构造对象
2 初始化对象
3 类型转换
1.2.1 整形可以隐式转换为Test类,那怎么显式转换呢?
上面提到了整型100隐式地先转换为Test类型的临时变量,通过上面代码,应该很容易就可以猜到,100是通过:Test(int d = 0){} 这个构造函数转换的。
这个时候我们在该构造函数前加一个显式转换的关键字explicit,然后再运行,截图如下:
由上图,我们在第9行的构造函数前面加了explicit显式转换关键字之后,在编译阶段就开始报错了,即程序必须显式转换才能运行。显式转换代码如下:
由上图,我们在第28行,显式地写明了要将整型100强制转换为Test类型的临时变量,并且Test类里面存在这么一个只有一个整型参数的构造函数,因此我们能够找到这么一个途径,因此现在程序可以成功运行了。
1.2.2 整形可以隐式转换为Test类,那Test类可以转换为整型么?
既然整型100可以隐式或者显式转换为Test类,那么Test类可以转换为整型么?
我们在30,31行加了2行代码,想将Test类的t1,赋值给int 类型的value
由上图,在编译阶段就报错了:error: cannot convert ‘Test’ to ‘int’ in assignment
由报错也说明了,找不到一个方式可以将Test类型转换为int类型,那么我们可以自己创造一个方式么?答案是可以的。这个时候,我们可以使用重载操作符operator关键字来实现:
这个时候,我们在20-23行,加了关于int类型转换的重载方法,在方法里面,我们直接返回了该类的私有变量data的值,这个时候,程序不再报错,可以顺利执行通过了。
因此,当系统没有提供一个隐式转换的方法时,我们可以借助重载操作符operator,自己写一个方法,这样C++就在Test类里面有一个int()的重载方法,并且传入的参数是Test类型。这时我们就可以将一个Test类型的变量赋值给一个int 类型的变量了。
2 本节小结
本节的重点是理解构造函数的3个作用:构造对象,初始化对象,类型转换。其中还需要理解类型转换里面发生的隐式或者显式转换,同时也简单了解了重载操作符operator的基本使用方式。