转换运算符(也称为用户定义转换)
在C++中,您可以创建转换运算符,这些运算符允许编译器在您的类型和其他定义的类型之间进行转换。转换运算符有两种类型,隐式和显式。
隐式转换运算符(C++98/C++03和C++11)
隐式转换运算符允许编译器将用户定义类型的值隐式转换(如int和long之间的转换)为其他类型。
下面是一个带有隐式转换运算符的简单类:
class my_string {
public:
operator const char*() const {return data_;} // This is the conversion operator
private:
const char* data_;
};
隐式转换运算符和单参数构造函数一样,都是用户定义的转换。当试图匹配对重载函数的调用时,编译器将授予一个用户定义的转换。
void f(const char*);
my_string str;
f(str); // same as f( str.operator const char*() )
一开始,这似乎非常有用,但问题是,隐式转换甚至在不需要时开始。在以下代码中,将调用void f(const char*),因为my_string()不是左值,因此第一个不匹配:
void f(my_string&);
void f(const char*);
f(my_string());
初学者很容易误解这一点,即使是有经验的C++程序员有时也会感到惊讶,因为编译器选择了他们没有怀疑的重载。这些问题可以通过显式转换运算符来缓解。
显式转换运算符(C++11)
与隐式转换运算符不同,显式转换运算符不会在您不期望的时候出现。以下是一个带有显式转换操作符的简单类:
class my_string {
public:
explicit operator const char*() const {return data_;}
private:
const char* data_;
};
请注意显式。现在,当您尝试从隐式转换运算符执行意外代码时,会出现编译器错误:
prog.cpp: In function ‘int main()’:
prog.cpp:15:18: error: no matching function for call to ‘f(my_string)’
prog.cpp:15:18: note: candidates are:
prog.cpp:11:10: note: void f(my_string&)
prog.cpp:11:10: note: no known conversion for argument 1 from ‘my_string’ to ‘my_string&’
prog.cpp:12:10: note: void f(const char*)
prog.cpp:12:10: note: no known conversion for argument 1 from ‘my_string’ to ‘const char*’
要调用显式转换运算符,必须使用static_cast、C样式转换或构造函数样式转换(即T(value))。
然而,有一个例外:允许编译器隐式转换为bool。此外,编译器在转换为bool后不允许再进行一次隐式转换(编译器一次允许进行2次隐式转化,但最多只能进行1次用户定义的转化)。
因为编译器不会抛出“过去”布尔值,所以显式转换运算符现在不再需要安全布尔值习惯用法。例如,C++11之前的智能指针使用安全布尔习惯用法来防止转换为整型。在C++11中,智能指针改用显式运算符,因为编译器在将类型显式转换为bool后,不允许隐式转换为整型。
继续重载新建和删除。