【C++ Operators】避免提供“类型转换函数”

隐式转换

  • C++允许编译器在不同类型之间执行隐式类型转换(implicit conversions);
  • 两种函数允许编译器执行这样的转换:
  1. 单自变量constructors
  2. 隐式类型转换操作符

单自变量constructors

能够以单一自变量成功调用的constructors。

如此的constructor可能拥有单一参数,也可能声明拥有多个参数,并且除了第一个参数之外都有默认值。

class Name
{
public:
	Name(const string& s);  //可以把string转换成Name
};

class Rational
{
public:
	Rational(int numerator = 0, int denominator = 1); 
							//可以把int转换成Rational
}

//调用如下
void TestFunc(Name myName)
{
	...
}

string strName;
TestFunc(strName); //调用成功,编译器调用了单参数的构造函数

单自变量construtors完成的隐式转换较难消除

解决:可以使用explicit声明进行消除。

//如需禁止调用:加上关键字explicit
class Name
{
public:
	explicit Name(const std::string& s); 
								//禁止调用进行隐式类型转换
};
template<class T>
class Array{
public:
    explicit Array(int size);
    ...
};

隐式类型转换操作符

关键字operator之后加上一个类型名称。

不能为此函数指定返回值类型,因为其返回值类型基本上已经表现于函数名称上,例如:

class Rational
{
public:
	...
	operator double() const; //将Rational转换为dobule
}

//该函数会在下面代码中自动调用
Rational r(1, 2);
double d = 0.5 * r; // 将r(1/2)转换成double,然后执行乘法运算

最好不要提供任何类型转换函数

在你从未打算也未于其的情况下,此类函数可能会被调用,而其结果可能是不正确的、不直观的程序行为,很难调试。
隐式类型转换,它们的出现可能导致错误(非预期)的函数被调用。

解决:以功能对等的另外一个函数取代类型转化操作符。

//为了允许将Rational转换为double
//以一个名为asDouble的函数取代operator double
class Rational
{
public:
	...
	double asDouble() const; //将Rational转换为double
};

//于是member function必须被明确调用
Rational r(1, 2);
cout << r; 			  //错误!Rational没有operator<<
cout << r.asDouble(); //可!以double的形式输出r
 

小结

大部分时候,"必须明白调用类型转换函数"虽然带来了些许不便,却可以为"不再默默调用那些其实并不打算调用的函数"而获得弥补;
(这就是为什么标注库中的 string 类型并未含有“从 string object 至 C-style char*”的隐式转换函数的原因,标准库提供了一个显示的 member function c_str() 执行上述转换行为)。

你可能感兴趣的:(C++进阶,c++,开发语言,笔记)