类型转换函数(三十五)

        我们之前在 C 语言中讲过类型转换,那么在 C++ 中是否还会有什么新特性呢?我们先来看看之前的类型转换是怎样的,标准数据类型之间会进行隐式的类型安全转换。转换规则如下

十余年的抚松网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。全网营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整抚松建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“抚松网站设计”,“抚松网站推广”以来,每个客户项目都认真落实执行。

类型转换函数(三十五)

        我们还是以代码为例来进行分析

#include 
#include 

using namespace std;

int main()
{
    short s = 'a';
    unsigned int ui = 100;
    int i = -200;   // safe
    double d = i;   // safe
    
    cout << "d = " << d << endl;
    cout << "ui = " << ui << endl;
    
    if( (ui + i) > 0 )
    {
        cout << "Positive" << endl;
    }
    else
    {
        cout << "Negative" << endl;
    }
    
    cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl;
    
    return 0;
}

        我们来试着打印下 d 和 ui 的值,如果 ui + i > 0,则打印 Positive,否则打印 Negative。最后看看 short 和 char 类型会转换成 short 吗?看看编译结果

类型转换函数(三十五)

        我们看到打印的是 Positive,也就说 ui + i > 0。根据数学知识,怎么可能呢?我们一会再来打印下他们相加的值看看,最后一个竟然打印的是 4,short 类型不是 2 吗?再看看我们上面的隐式类型转换规则,short 和 char 都会转换成 int 类型。而 int 也会隐式转换成 unsigned int,所以结果并不惊奇,我们来看看他们相加的值是多少?

类型转换函数(三十五)

        我们看到他们相加是个那么大的随机数,这肯定大于 0 啦。那么在 C++ 中问题来了:普通类型与类类型之间能否进行类型转换?类类型之间能否进行类型转换?下来我们来看看示例代码

#include 
#include 

using namespace std;

class Test
{
    int mValue;
public:
    Test()
    {
        mValue = 0;
    }
    
    Test(int i)
    {
        mValue = i;
    }
    
    Test operator + (const Test& t)
    {
        Test ret(mValue + t.mValue);
        
        return ret;
    }
    
    int value()
    {
        return mValue;
    }
};

int main()
{
    Test t;
    
    t = 5;
    
    cout << "t.value() = " << t.value() << endl;
    
    Test r;
    
    r = t + 10;
    
    cout << "r.value() = " << r.value() << endl;
    
    return 0;
}

        我们来看看这样直接 t = 5,和 r = t + 10;可以通过吗?看看编译结果

类型转换函数(三十五)

        我们看到编译通过了,并且也执行成功。下来我们来分析下为什么会支持这样的写法,在构造函数中可以定义不同类型的参数,参数满足这三个条件时便称之为转换构造函数:a> 有且仅有一个参数;b> 参数是基本类型;c> 参数是其它类类型。那么我们从 C 的角度来看看强制类型转换:int i = int(1.5);Test t = Test(100);这样便不难解释了,为了显示编译器的强大,编译器会尽力尝试让源码通过编译,如下

类型转换函数(三十五)

        编译尽力尝试的结果便是隐式类型转换,使用转换构造函数来进行转换。但是隐式类型的转换会让程序以意想不到的方式进行工作,是工程中的 bug 的重要来源。如果在那块我们只是手误写成那样了,编译器却让它通过了,我们看到运行结果不对,bug 却无从查起。。。

        所以为了解决这个问题,我们便在工程中通过 explicit 关键字来杜绝编译器的转换尝试,转换构造函数被 explicit 修饰时只能进行显示转换,转换方式是:a> static_cast (value);b> ClassName(value);c> (ClassName)value;但是在 C++ 中我们推荐的是第一种写法,最后一种往往是不推荐的。下来我们就来试试 explicit 关键字,在 Test(int i) 成员函数前加上,看看编译器还会不会进行隐式类型转换

类型转换函数(三十五)

        那么编译器直接报错了,我们再来试试手动的进行类型转换,我们将第 37 和 43 行改为下面那样

    t = static_cast(5);
    
    r = t + static_cast(10);

        我们来看看编译结果

类型转换函数(三十五)

        结果和我们之前的是一样的。那么从普通类型能够转换到类类型,类类型能否转换到普通类型呢?我们在 C++ 类中可以定义类型转换函数,类型转换函数用于将类对象转换为其它类型,语法规则如下

类型转换函数(三十五)

        下来我们来试试编写类型转换函数

#include 
#include 

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    
    int value()
    {
        return mValue;
    }
    
    operator int ()
    {
        return mValue;
    }
};

int main()
{
    Test t(100);
    int i = t;
    
    cout << "t.value() = " << t.value() << endl;
    cout << "i = " << i << endl;
    
    return 0;
}

        我们来试试看这样行不行呢,编译结果如下

类型转换函数(三十五)

        我们看到类对象已经成功转换为普通数据类型。那么类型转换函数具有以下几个特点:a> 与转换构造函数具有相等的地位;b> 使得编译器有能力将对象转化为其它类型;c> 编译器能够隐式的使用类型转换函数。同样,编译器也会尽量尝试让源码通过编译,如下

类型转换函数(三十五)

        那么便不难解释我们上面的程序了。既然这样都可以转换,类类型之间可以相互转换吗?我们来看看

#include 
#include 

using namespace std;

class Value
{
public:
    Value()
    {
    }
};

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    
    int value()
    {
        return mValue;
    }
    
    operator Value ()
    {
        Value ret;
        
        return ret;
    }
};

int main()
{
    Test t(100);
    Value v = t;
    
    return 0;
}

        那么我们看到 Test 和 Value 是两个不同的类,它们能转换成功吗?我们来看看编译结果

类型转换函数(三十五)

        编译通过,当然没什么输出了,我们在程序中又没有什么打印语句。那么如果我们在类 Value 中加上转换构造函数呢?编译器会作何选择?这时我们的 VAlue 类将会变成

class Value
{
public:
    Value()
    {
    }
    Value(Test& t)
    {
    }
};

        我们来编译下看看结果

类型转换函数(三十五)

        编译器报错了,它犯难了。这是不知道是调用 Test 类的类型转换函数还是 Value 类的转换构造函数了,像这种情况,我们在转换构造函数前加上 explicit 关键字,编译器便不会去隐式的调用转换构造函数了。我们在类型转换函数中加上一句输出,看看结果

类型转换函数(三十五)

        我们可以看出调用的确实是类型转换函数。那么我们无法抑制隐式的类型转换函数调用,类型转换函数便可能与转换构造函数造成冲突,工程中以 Type toType() 的共有成员函数代替类型转换函数。

        通过对类型转换函数的学习,总结如下:1、转换构造函数只有一个参数;2、转换构造函数的参数类型是其它类型,它在类型转换时被调用;3、隐式类型转换时工程中 bug 的重要来源,explicit 关键字用于杜绝隐式类型转换;4、C++ 类中可以定义类型转换函数;5类型转换函数用于将类对象转换为其它类型,它与转换构造函数具有同等的地位;6、工程中以 Type toType() 的共有成员函数代替类型转换函数。

        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。


网站栏目:类型转换函数(三十五)
文章转载:http://scyanting.com/article/jphesi.html