隐式转换在现代C ++中是好还是坏?

时间:2014-03-04 00:25:24

标签: c++ c++11 implicit-conversion

this proposal中:

  

N3830 Scoped Resource - 标准库的通用RAII包装器

提供scoped_resource RAII包装器。

在第4页上,有一些代码如下:

auto hFile = std::make_scoped_resource(
      ...
    );    
...

// cast operator makes it seamless to use with other APIs needing a HANDLE
ReadFile(hFile, ...);

Win32 API ReadFile() takes a raw HANDLE parameter,而hFilescoped_resource的实例,因此为了使上述代码有效,有一个隐式强制转换运算符已实现scoped_resource

但是,避免这种隐式转换不是“现代”建议吗?

例如,ATL / MFC CString具有隐式转换(强制转换运算符)到LPCTSTRconst char/wchar_t*,即原始C字符串指针)相反,STL字符串具有显式 c_str()方法。

类似地,像unique_ptr这样的智能指针有一个显式 get()方法来访问底层包装指针;而且这篇关于隐式转换的建议似乎也出现在这篇博文中:

  

Reader Q&A: Why don’t modern smart pointers implicitly convert to *?

那么,这些隐式转换(如ATL / MFC CString和新提出的scoped_resource)是否适用于现代C ++?

从编码的角度来看,我会说能够直接将RAII包装器 - 无论是CString还是scoped_resource传递给期望“原始”参数的C API(如原始C字符串指针或原始句柄,依赖于隐式转换,而不调用某些.GetString() / .get()方法,看起来非常方便。

3 个答案:

答案 0 :(得分:3)

以下是C++ Primer 5th edition的引用。

  

注意:避免过度使用转换函数

     

与使用重载运算符一样,明智地使用转换运算符即可   大大简化了类设计师的工作,使得使用类更容易。   但是,某些转换可能会产生误导。转换运算符是   当类类型之间没有明显的单一映射时会产生误导   和转换类型。

     

例如,考虑一个代表Date的类。我们可能会这么认为   提供从Dateint的转换是个不错的主意。然而,   转换函数应该返回什么值?该函数可能会返回   年,月和日的十进制表示。例如,1989年7月30日可能表示为int值19800730.或者,转换运算符可能返回一个int,表示自某个纪元点(例如1970年1月1日)以来经过的天数。这两个转换都具有期望的属性,后面的日期对应于更大的整数,所以要么可能有用。

     

问题是a之间没有单一的一对一映射   类型为Date的对象和类型为int的值。在这种情况下,最好不要   定义转换运算符。相反,这个类应该定义一个或   更多普通会员以这些形式提取信息。

所以,我可以说的是,在实践中,类应该很少提供转换运算符。如果转换自动发生而不是得到帮助,用户往往更容易感到惊讶 存在转换。但是,这个规则有一个重要的例外 thumb:类将转换定义为bool的情况并不少见。 在标准的早期版本中,要定义转换的类 bool遇到了一个问题:因为bool是一个算术类型,所以是类型对象 转换为bool可以在任何需要算术类型的上下文中使用。 这种转换可能以令人惊讶的方式发生。特别是,如果istream有一个 转换为bool,以下代码将编译:

int i = 42;
cin << i; // this code would be legal if the conversion to bool were not explicit!

您应该使用explicit转换运算符。以下是一个小例子:

class small_int 
{
private: 
  int val;
public:
  // constructors and other members
  explicit operator int() const { return this->val; }
}

......并且在程序中:

int main()
{
  SmallInt si = 3; // ok: the SmallInt constructor is not explicit
  si + 3; // error: implicit is conversion required, but operator int is explicit
  static_cast<int>(si) + 3; // ok: explicitly request the conversion

  return 0;
}

答案 1 :(得分:1)

我认为隐式转换对于应用程序程序员来说是好的/方便的,但对于库开发人员来说则不好,因为它们引入了复杂性和其他问题:一个很好的例子是隐式转换和模板推导之间的相互作用。

从库的角度来看,将语言功能约束到最小集合更容易。为此,如果删除一些重载和默认参数,您甚至可以说库更容易维护。它对应用程序员来说不太方便,但是模糊性和复杂性较少。

所以,它真的是方便和简单之间的选择。

答案 2 :(得分:0)

它在很大程度上取决于确切的转换类型,但是,一般来说,在某些方面,隐式转换可能会引入问题,而显性则可能不会。

通常,在编程中明确地做任何事情都是一种更安全的方式。

有关C++ in general以及特别是implicitexplicit次转化的良好信息来源。