C++核心准则边译边学-X.5:尽量不使用类型转换
翻译
按照C++核心准则的说法,应该尽量减少类型转换的使用,如果必须使用则使用narrow_cast和narrow。以下分几种情况讨论这个问题。
本来就不应该使用的情况:
观察如下代码:
class BaseClass{public: void bfun(){ cout << "BaseClass::bfun()" << endl; } virtual void vfun() { cout << "BaseClass::vfun()" << endl; }};class SubClass : public BaseClass{public: virtual void vfun() { cout << "SubClass::vfun()" << endl; }};SubClass是BaseClass的派生类,可以说SubClass就是BaseClass,因此SubClass类型的指针向Base类型指针赋值的时候就不需要转换。
BaseClass* bc = new SubClass();bc->bfun();bc->vfun();
使用模板可以解决的情况:
观察下面的代码:
int mul(int a, int b) { return a * b;}
int main(){ cout << mul(3, 5) << endl; cout << mul(2.7, 5.6) << endl; return 0;}代码中定义了一个整形数字的乘法函数,如果实参是整数的话函数可以正常执行;如果实参是浮点数,一方面编译会产生警告,另一方面计算会丢失精度(和警告的结果一致)。对实参进行类型转换虽然可以解决警告信息但是但是却无法解决丢失精度的问题。这时较好的的解决方式是使用模板:
template<typename T1, typename T2>auto mul(T1 a, T2 b) ->decltype(a*b){ return a * b;}代码中使用了C++11新特性模板函数返回类型后置技术实现了更大的灵活性(两个实参可以是不同类型)。
int main(){ cout << mul(3, 5) << endl; cout << mul(2.7, 5.6) << endl; cout << mul(2.7, 5) << endl; return 0;}无论哪种情况都不会出现编译警告,都可以得到正确的结果。
使用narrow_cast和narrow
如果设计者处于某种目的就是希望进行窄化类型转换时可以使用gsl提供的narrow_cast进行明确地表达这层意思。
cout << mul(narrow_cast<int>(3.4), narrow_cast<int>(2.8)) << endl;
如果希望进行类型转换,但是不希望发生窄化的情况下,可以使用narrow类型转换:
cout << mul(narrow<int>(3), narrow<int>(8)) << endl;cout << mul(narrow<int>(3.4), narrow<int>(2.8)) << endl;
第一种情况没有发生窄化,因此可以正常执行;第二种情况发生的浮点数到整数的窄化,会触发异常。
觉得本文有帮助,欢迎点赞并分享给更多的朋友!
阅读更多更新文章,请关注微信公众号【面向对象思考】