【问题标题】:conversion operator as standalone function转换运算符作为独立函数
【发布时间】:2011-01-11 10:09:43
【问题描述】:

为什么 C++ 要求用户定义的转换运算符只能是非静态成员? 为什么不允许像其他一元运算符一样使用独立函数? 像这样的:

operator bool (const std::string& s) { return !s.empty(); }

【问题讨论】:

  • 这会很方便在std::stringQString 之间进行转换,这对我的代码的可读性来说是酸的。

标签: c++ type-conversion conversion-operator


【解决方案1】:

我能想到的一个原因是防止将隐式转换应用于被强制转换的东西。在您的示例中,如果您说:

 bool( "foo" );

然后“foo”将被隐式转换为字符串,然后将应用您提供的显式布尔转换。

如果 bool 运算符是成员函数,则这是不可能的,因为隐式转换不会应用于 *this。这大大减少了歧义的可能性——歧义通常被视为“坏事”。

【讨论】:

  • 我不明白你的论点。您给出的示例不是隐式转换。另一方面,定义转换运算符的主要原因是使用隐式转换。
  • @shura 是的。 "foo" 被隐式转换为字符串,然后显式转换为布尔值。我已经更新了我的答案以澄清这一点。
  • 为了进一步解释歧义,这可以被视为从指针到bool的转换,尽管它总是会导致true
  • 但是为什么 bool( "foo" ) == false 是个问题呢?这正是问题中定义的显式转换运算符的含义(如果有效)。
  • C++中有一个explicit关键字。
【解决方案2】:

通过将转换运算符保留在类中,您可以让类的作者控制它的转换方式(它可以防止用户创建隐式转换)。作为实施者,我认为这是一个优势,如implicit conversions does have its issues

能够将一个对象作为另一个对象传递,并让它通过转换函数是有区别的。前者传达对象是给定类型的信息,而后者则向新读者展示这两种类型之间存在差异并且需要进行转换。

【讨论】:

  • 它没有提供任何额外的控制。我可以(并且可能应该)简单地编写一个 ToBool() 函数来进行转换。
  • 它也是如此 :) 隐式转换与 ToBool() 完全不同。如果可以的话,我会将 std::string 隐式转换为 char*,但幸运的是 Stroustrup 等人。知道得更好。
【解决方案3】:

有一组运算符必须作为非静态成员函数重载:赋值、下标、函数调用、类成员访问、转换函数。

我猜标准的委员会或 Stroustrup 只是觉得如果允许将这些非常特殊的行为从外部注入到类中可能会太混乱。


我想获得答案的最佳方式是给作者发电子邮件。

【讨论】:

  • 嗯,这不是在标准委员会第一次开会之前很久就决定了吗?
  • 或许 Stroustrup 也有这种感觉。这只是一种猜测。这些都有什么共同点,所以他们都必须是成员?我没有看到任何技术原因,为什么他们应该(好吧,分配会有技术问题,因为编译器会合成它)。
  • 很伤心,因为将“从 std::string”转换为其他东西是一种普遍的愿望
【解决方案4】:

无论如何,隐式的用户定义转换都是不受欢迎的。不要使用它们。就假装他们不在那里。更不用说考虑以新的方式来介绍它们了。

无论如何,我猜他们不在那里,因为他们可以做足够多意想不到的事情。包含一个为其他地方定义的类引入这种转换的新标头可能会导致更加混乱的错误。

【讨论】:

  • 那么当 C++0x 允许将explicit 与强制转换运算符一起使用时,您的论点仍然成立吗?我可以设想一些只能与 static_cast 一起使用的独立演员表运算符的用处。
  • 并不是说我是隐式用户定义转换的忠实粉丝。我不想像我的示例那样将字符串隐式转换为布尔值。但有时它们很有用。以 std::string(const char*) 为例。
  • @shura: std::string(const char*)if(my_stream) 是我看到的唯一两个有用的隐式转换示例,它们一遍又一遍地重复。 (我认为两者都值得商榷。)有没有人想出另一个有用的例子?
猜你喜欢
  • 2011-01-27
  • 2021-12-04
  • 2019-02-04
  • 2010-11-30
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多