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,而hFile
是scoped_resource
的实例,因此为了使上述代码有效,有一个隐式强制转换运算符已实现scoped_resource
。
但是,避免这种隐式转换不是“现代”建议吗?
例如,ATL / MFC CString
具有隐式转换(强制转换运算符)到LPCTSTR
(const 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()
方法,看起来非常方便。
答案 0 :(得分:3)
以下是C++ Primer 5th edition的引用。
注意:避免过度使用转换函数
与使用重载运算符一样,明智地使用转换运算符即可 大大简化了类设计师的工作,使得使用类更容易。 但是,某些转换可能会产生误导。转换运算符是 当类类型之间没有明显的单一映射时会产生误导 和转换类型。
例如,考虑一个代表Date的类。我们可能会这么认为 提供从
Date
到int
的转换是个不错的主意。然而, 转换函数应该返回什么值?该函数可能会返回 年,月和日的十进制表示。例如,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以及特别是implicit和explicit次转化的良好信息来源。