条款五:对自定义的类型转换保持警觉
2016-08-09 10:47
162 查看
条款五:对自定义的类型转换保持警觉
C++的强大之一是它不同于C语言严格的数据类型检查,但是有些情况下C++编译器为了方便用户操作给用户带来的一些麻烦也不容忽视。1. 隐式数据类型转换
这里说到的隐式类型转换和普通的隐式数据类型转换相同,但是直接操作符却不是来自系统而是用户,比如有一个类:class fun { int deno; int mole; public: fun(int d, int m) :mole(m), deno(d){} operator double()const { return deno / static_cast<double>(mole); } };
如果我们执行代码打印一个fun类型的对象不会报错而是直接输出一个double,因为发生了隐式类型转换,这可能在这里影响不大,但是有些时候的确会造成错误。解决方法也很简单,自定义一个<<重载操作符即可。或者自定义一个成员函数来实现operator double()的功能。
2. 构造函数导致的隐式类型转换
在C++中隐式数据类型转换不仅仅来自于来源于C语言的数据类型转换,而且带有参数的构造函数也会触发隐式类型转换。比如有一个类template<class T> class Array { public: Array(int size) { } T& operator[](int index) { return 0; } }; //这个类只是简写,理解意思就行 bool operator==(Array<int> _rst, Array<int> _snd) { }
在对类Array执行if (_array_rst[2] == _array_snd[2])因为大意写成if (_array_rst == _array_snd[2]),这样编译器不会报错还会进行比较,因为_array_snd[2]是一个int数,而Array的拷贝构造函数需要一个int类型这就触发了隐式类型转换。这可能在工程中导致一些不可预见的错误。
解决的办法是使用explicit关键字对构造函数进行限制,这样编译器就不会触发因拷贝构造函数引起的饮食类型转换。
解决办法
1. 添加explicit关键字,禁止拷贝构造函数的隐式类型转换
2. 使用嵌套类。如将以上类修改为
template<class T> class Array { public: class ArraySize { private: int _size; public: int size() { return _size; } ArraySize(int num) :_size(num){} }; Array(ArraySize size) { } T& operator[](int index) { return 0; } };
这就是一个代理类(proxy)可以解决隐式类型转换问题
总结
对于用户自定义类型转换,避免用它;而拷贝函数导致的隐式类型转换要考虑所做的具体项目的环境不能说那一种方法最好,深思熟虑。相关文章推荐
- 深入Atlas系列:Web Sevices Access in Atlas示例(5) - 自定义TypeConverter把基础类型转换为复杂类型
- 关于C++和C#的自定义数据类型转换的一些思考
- Castle的自定义类型转换
- .net类型自定义隐式(显式)转换操作的位置问题
- C#中的自定义类型转换
- 当重载了自定义类型的转换操作符时,应该注意的一点
- c#实现隐式的用户自定义类型转换(关键字implicit operator)
- 自定义数据类型转换Demo
- explicit和implicit属于转换运算符,如用这两者可以让我们自定义的类型支持相互交换。
- Castle的自定义类型转换
- 深入Atlas系列:Web Sevices Access in Atlas示例(5) - 自定义TypeConverter把基础类型转换为复杂类型
- 让自定义的类型可以和任意的类型之间转换
- 让自定义的类型可以和任意的类型之间转换
- 让自定义的类型可以和任意的类型之间转换
- 自定义显式类型转换 --explicit
- ASP.Net中用ViewState存储自定义复杂对象后类型转换的一个问题
- 让自定义的类型可以和任意的类型之间转换
- 让自定义的类型可以和任意的类型之间转换
- 自定义bool类型转换操作符
- 条款24:若所有参数皆需类型转换,请为此采用non-member函数