- C++的隐式转换,有好处也有坏处,因为是“自动的”,导致有时它的行为与我们预期不符。
- explicit是用于指定显示类型转换的,C++11
#include <iostream>
using namespace std;
template <typename T>
class Ptr
{
public: Ptr(T* p): _p(p) {}
operator bool() const
{
if (_p != 0)
return true;
else
return false;
}
private: T* _p;
};
int main()
{
int a;
Ptr<int> p(&a);
if (p) // 自动转换为bool型,没有问题
cout << "valid pointer." << endl; // valid pointer.
else
cout << "invalid pointer." << endl;
Ptr<double> pd(0);
cout << p + pd << endl; // 1,相加,语义上没有意义
}
// 编译选项:g++ 3-4-2.cpp
隐式转换可能带来的问题:
参考以上这段代码,因为实现了bool语句的重载,在执行if判断时,会执行bool类型隐式转换;
然而最后一行的p+pd中,因为它们都实现了bool重载并且没有加以转换限制,因此编译可通过,但无意义 。
解决方案:
参考这段代码:
class ConvertTo {};
class Convertable {
public:
//允许显式类型转换,从convertable到convertTo
//此时拷贝构造和非显式类型转换将被禁止
explicit operator ConvertTo () const
{
return ConvertTo();
}
};
void Func(ConvertTo ct) {}
void test()
{
Convertable c;
ConvertTo ct(c); // 直接初始化,通过
ConvertTo ct2 = c; // 拷贝构造初始化,编译失败
ConvertTo ct3 = static_cast<ConvertTo>(c); // 强制转化,通过
Func(c); // 拷贝构造初始化,编译失败
} // 编译选项: g++ -std=c++11 3-4-3.cpp
以第二段代码为启发,当我们将第一段代码的operator bool()改成explicit operator bool()后,隐式转换和拷贝构造将被禁止,此时我们既可以使用if§这样显式转换的语句(因为if语句的显式类型就是bool),也能禁止 p+p0这样的语句通过编译 (因为operator + 是不接收bool类型的参数,而加explicit之前能执行,是因为p和p0被隐式转换成int类型了)
总结:
- explicit 从C++11开始可以用于自定义的类型转换符中
- 加了explicit后,只允许显式转换(直接初始化),拷贝构造和隐式转换将被禁止,通常来说,也就不能够通过赋值表达式或函数参数的方式来获得一个目标类型(有时赋值表达式或函数参数产生的目标类型并非我们本意,是疏忽)
- 加了explicit后,除直接初始化外,还可以通过static_cast(Source),将Source转化为Target类型
2022/12/01 00:26