首页 > 代码库 > 编写高质量代码——提防隐式转换带来的麻烦
编写高质量代码——提防隐式转换带来的麻烦
在C/C++ 语言,允许在不同类型的数据之间进行某一操作或混合操作,如果类型不同,则要将数据转换成相同的数据类型(隐式转换和显示转换)。
=========================
隐式转换主要发生的情形:
▉基本类型之间的隐式转换
C/C++ 中规定的两个通用转换原则:
1)为防止精度损失,类型总是被提升为较宽的类型。
2)所有含有小于整数类型的算术表达式在计算之前其类型都被转换成整形。
对于C++最直接的害处是:可能导致 重载函数 产生二义性。
例如:
void Print(int inval);
void Print(float fval);
int ival = 2;
float fval = 2.0f;
Print(ival); // OK, int-version
Print(fval); // OK, float-version
Print(1); //OK, int-version
Print(0.5); //ERROR ! !
▉T* 指针到 void* 的隐式转换
▉non-explict constructor 接受一个参数的用户定义类对象之间隐式转换:
class A{
public:
A(int x):m_data(x){}
private:
int m_data;
};
void DoSomething(A aObject);
DoSomething(20);
------------------------------------------------------------------
调用DoSomething() 函数时,实参和形参类型不一致,但是类A的构造函数含有一个 int 类型的参数,编译器会以 20 为参数调用A的构造函数,以便构造临时对象,然后传给 DoSomething() 函数。
------------------------------------------------------------------
当无法完成类似上述的直接隐式转换时,编译器会尝试间接的方式:
void DoSomething(A aObject);
float fval = 20.0f;
DoSomething(fval);
------------------------------------------------------------------
Note:1)隐式转换一个误用也许会引起难以捉摸的错误
2)隐式转换过程中需要调用类的构造函数、析构函数,如果这种转换代价很大,那么这样的隐式转换将会影响系统性能。
------------------------------------------------------------------
相对安全的隐式转换:子类到基类的隐式转换 和const 到 non-const 的同类型隐式转换=========================
控制隐式转换的两条有效途径:
●使用具名转换函数:
用 operator as_T() 替代 operator T()(T 为 C++ 数据类型)
●使用 explict 限制的构造函数(只针对有一个单参数构造函数的用户自定义类型)
class Widget{
public:
Widget( unsigned int factor );
Widget( const char* name, const Widget* other = NULL );
};// 在只有一个参数时,unsigned int 和 const char* 参数类型的数据均可隐式转换为自定义的 Widget 类型
控制以上隐式转换的方法:为单参数的构造函数加explicit关键字
class Widget{
public:
explicit
Widget( unsigned int factor );
explicit
Widget( const char* name, const Widget* other = NULL );};