类型转换函数(三十五)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类型转换函数(三十五)相关的知识,希望对你有一定的参考价值。
我们之前在 C 语言中讲过类型转换,那么在 C++ 中是否还会有什么新特性呢?我们先来看看之前的类型转换是怎样的,标准数据类型之间会进行隐式的类型安全转换。转换规则如下
我们还是以代码为例来进行分析
#include <iostream> #include <string> 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 <iostream> #include <string> 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 <ClassName>(value);b> ClassName(value);c> (ClassName)value;但是在 C++ 中我们推荐的是第一种写法,最后一种往往是不推荐的。下来我们就来试试 explicit 关键字,在 Test(int i) 成员函数前加上,看看编译器还会不会进行隐式类型转换
那么编译器直接报错了,我们再来试试手动的进行类型转换,我们将第 37 和 43 行改为下面那样
t = static_cast<Test>(5); r = t + static_cast<Test>(10);
我们来看看编译结果
结果和我们之前的是一样的。那么从普通类型能够转换到类类型,类类型能否转换到普通类型呢?我们在 C++ 类中可以定义类型转换函数,类型转换函数用于将类对象转换为其它类型,语法规则如下
下来我们来试试编写类型转换函数
#include <iostream> #include <string> 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 <iostream> #include <string> 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。
以上是关于类型转换函数(三十五)的主要内容,如果未能解决你的问题,请参考以下文章