C++初级主题--(3)构造函数的作用

一.序
构造函数有三个作用:构造对象、初始化对象、类型转换
二.Attention
1.构造对象
当调动构造函数时,毫无疑问将会有一个新的对象被构造出来
2.初始化对象与类型转换
问题1:变量给对象赋值可取?

#include<iostream>
using namespace std;
class Test
{
public:
    Test(int d = 0) : data(d)
    {}
private:
    int data;
};
void main()
{
Test t;
t = 100;
}

如上,t是实例化出的对象,将一个int型的常量赋给对象,这样正确吗?答案是肯定的!原因:
无论是C,还是C++,不同类型之间赋值,都要进行类型转换,表象是右值给左值赋值,实质上,此时,赋值中间会产生临时对象/临时变量,是临时对象/临时变量在给左值赋值(这一点十分重要!)。
本例中,t = 100实质上做了三步操作
(1)构造出临时对象,假设临时对象为tmp(tmp为Test类型)
(2)tmp.data = 100;
(3)t = tmp;//对象给对象赋值涉及到赋值运算符的重载,后续在赋值运算符的重载函数一文中介绍。
但是请看下列程序:

#include<iostream>
using namespace std;
class Test
{
public:
    explicit Test(int d = 0) : data(d)
    {
        cout<<"Create new object:"<<this<<endl;
    }
    ~Test()
    {
        cout<<"Free object:"<<this<<endl;
    }
    /*Test()
    {}*/
private:
    int data;
};
void main()
{
    Test t;
    t = 100;//错误    1   error C2679: 二进制“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)
}

为什么会报错?原因是构造函数前加入了explicit关键字

C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。

简单来说,就是要进行显式转换。于是将22行改成t = (Test)100即可。这样使得代码的可读性更高,给人的感觉是对100进行强制类型转换,使得它可以用来初始化t.

问题2:如何用对象给变量赋值?

Test t(100);
int value;
value = t;//错误  1   error C2440: “初始化”: 无法从“Test”转换为“int”

要进行上述操作,需要重载int,代码如下:

#include<iostream>
using namespace std;
class Test
{
public:
    explicit Test(int d = 0) : data(d)
    {
        cout<<"Create new object:"<<this<<endl;
    }
    ~Test()
    {
        cout<<"Free object:"<<this<<endl;
    }
public:
    operator int()//对int进行重载
    {
        return data;
    }
private:
    int data;
};
void main()
{
    Test t(100);
    int value; 
    value= t;
}

问题3:构造函数影响着类型转换
是不是所有的类型都能够通过构造函数进行转换呢?不一定

#include<iostream>
using namespace std;
class Test
{
public:
    Test()
    {
        data = 0;
    }
    ~Test()
    {
        cout<<"Free object:"<<this<<endl;
    }
private:
    int data;
};
void main()
{
    Test t;
    t = 100;//错误    1   error C2679: 二进制“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)

}

此时,无法生成中间的临时对象。更何谈将100赋值给中间临时对象tmp的data,更不要说用tmp初始化t了。
将代码进行更改,是可以用100构造出中间临时对象即可:

#include<iostream>
using namespace std;
class Test
{
public:
    Test(int d) : data(d)
    {
        cout<<"Create new object:"<<this<<endl;
    }
    Test()
    {
        cout<<"Create new object:"<<this<<endl;

        data = 0;
    }
    ~Test()
    {
        cout<<"Free object:"<<this<<endl;
    }
public:
    operator int()
    {
        return data;
    }
private:
    int data;
};
void main()
{
    Test t;
    t = 100;
}

这里写图片描述
可以看到构造函数调动了两次

三.总结

不同类型之间进行赋值,一定会调动构造函数产生中间的临时变量,如果不能产生,就意味着这样的做法是不能编译通过的。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值