c++中隐式类型转换通常是编译器来完成的,当你的类型不匹配时,编译器会“智能”的帮你找到“正确”的类型并帮你转换。当然有些类型转换是我们所希望的,有些则是编译器“自以为是”的转换,不是我们所期望的。所以我们要了解什么时候转换会发生,怎么发生,才能更好的控制程序。
c++中隐式类型转换大致可以分为两种,一是用到的地方进行类型转换,二是变量被定义时的类型转换。
用到的地方进行隐式类型转换:比较简单的事 当你需要一个int是 你给他一个short这个时候就会发生隐式类型转换, short--->int。
举一个类的例子:比如你有一个Class Base
class Base
{
public:
Base();
~Base();
void SetData(double data)
{
m_data = data;
}
private:
double m_data;
};
main函数中是这样的:
Base b;
b.SetData(0.1);
cout << b <<endl;
这样是编译不过的,因为Base没有<<操作,但是我还要这种情况下输出b怎么办?
有几种方法:1 重载<<这个操作符,2 加一个GetData的方法, 3 重载double类型转换操作符。
这里我们说一下第三种,因为他可以触发用的时候隐式类型转换,给Base类加一个方法
operator double()
{
return m_data;
}
这样上面的main函数可以顺利编过并正确执行,
cout << b <<endl;
这里发生了隐式类型转换 Base -->double,double有<<这个操作符。
c++确实够灵活,有事你也确实需要这种转换,但是建议不要这样用,可以设计一个方法如ToDouble()这样既直观又明确,还可以防止发生隐式类型转换。
下面说一下定义变量时发生的隐式类型转换
我这里举一个简单的例子,实际情况要比这复杂的多,而且也非常不易发现,这里只是抛砖引玉,希望可以用好的方式避免这种行为发生
现在有两个类:
class Base
{
public:
Base(double date) : m_data(date)
{
cout << "Base" << endl;
}
private:
double m_data;
};
class Other
{
public:
Other(Base b)
{
cout << "Other(Base b)" << endl;
}
};
main函数中这么用:
Other other(0.1);
这里发生了0.1--->Base的隐式类型转换,Base对象再给Other。在实际情况中这可能是我们不想要的结果,可以通过 explicit 关键字杜绝这种情况的发生。
我们改变Base类为:
class Base
{
public:
explicit Base(double date) : m_data(date)
{
cout << "Base" << endl;
}
private:
double m_data;
};
explicit 只应用与一个参数的构造函数,因为2个或以上的参数不会发生隐式类型转换的。
总结: 我们编程中应该尽量避免隐式类型转换,因为隐式类型转换可能发生我们意料之外的结果,类型转换我们尽量避免,如果一定需要类型转换,可以显示的强制类型转换,参见上一篇 c++的强制类型转换进行尽量安全的类型转换