c++ - 为什么我不能将C++转换运算符作为非成员函数重载于类之外?

标签 c++ c++11 operator-overloading standards

之前曾有人问过这个问题,但是当他从未真正得到真正的答案时,我觉得提问者急于将答案正确。也许没有理由,您需要告诉我,稍后需要将其放入标准中。
What is the rationale to not allow overloading of C++ conversions operator with non-member functions

我正在寻找不允许将其作为当前标准设计一部分的具体原因。基本上,当重载类型转换运算符以定义两种类型之间的隐式转换时,此重载定义必须是要从其转换的类的成员,而不是类外部的成员。显而易见的问题是,如果您出于某种原因确实无法修改类型,但是为了简化语法(尽管隐式转换有弊端),则希望在它们之间进行隐式转换(或者隐式转换的弊端),或者因为您有很多其他类型依赖于隐式转换的代码,标准或自定义...如果无法向类中添加适当的隐式转换,则无法执行此操作,因此您需要使用常规功能(如常规函数)进行变通,以解决可能的问题否则是隐式转换的便利。

另外,是否真的可能存在将这些转换添加到类之外的计算开销?我的看法是,编译器很容易在确定可用的函数时将外部隐式转换函数与它们所转换的类相关联,以便像该类的一部分一样执行代码就效率而言。唯一的缺点是建立初始关联必须要做的额外工作,但这几乎没有。

我不会以“因为标准这样说”或“因为隐式转换不好”作为答案。当他们编写实际标准时,肯定会有一个原因。

(我不是专家,我还在学习语言。)

编辑,回复:
好吧,我想情况可能是这样的,是的,您更改了头文件,但是您不做的是覆盖现有的文件,因为那会很糟糕。您将基于旧的头文件创建一个新的头文件以适应更改。假定旧代码已经在目标文件中进行了编译,而更改 header 只是告诉编译器您在其他地方添加了其他代码。它不会更改旧代码的功能,因为它已经编译并且不依赖于此(即,某些供应商将您的目标代码和 header 交给了您)。如果我可以修改和重新编译将用于转换的代码,那么您就无法让我在外部编写转换函数,我不会这样做,这太令人困惑了。您不必在每个标题中随机搜索正确的定义;如果我自己编写代码,则将创建一个自定义 header ,该 header 具有一个高度可见的部分,其中添加到供应商提供的 header 中的内容是该 header ,并且该 header 相对于哪个 header 将是相对显而易见的,因为它将与相关的类型,其他 header 将使用其原始名称来命名,因此您将知道它们没有更改。并且您将有一个仅包含转换定义的相应文件,因此我的修改将是自包含的,与原始目标代码分离,并且相对容易找到。当然,这与在代码中找出适用转换函数的实际工作有所不同。我认为您会发现各种情况,这些情况很容易确定,并且足够自然地使用,可以出于您自己的目的添加到这样的现有库中。如果我使用的是我无法真正修改的商业代码,并且看到一种情况,可以通过使用转换功能将其与我自己的某些东西集成来改善我正在做的事情,那么我可能会发现自己想要这样做这。当然,对于仅阅读a = b的第三方来说,这样的事情并不明显,他们不知道我的转换是怎么回事,但是如果您知道并且它读起来很好,那么它就可以工作。

我很欣赏关于标准决策如何起作用的见解,这绝对是您可以忽略的一种附带事物。

最佳答案

  • 除了具有非明确的转换运算符外,例如在类中使用operator bool()时,您还可以让非显式构造函数在要转换到的类中使用单个参数,以此作为引入用户定义的转换的方式。 (未提及)
  • 关于为什么不能在不修改它们的定义的情况下在AB这两种类型之间引入用户定义的转换的原因……这会造成困惑。

    如果可以这样做,则可以在头文件中进行,并且由于引入新的用户定义的转换可以更改代码的含义,因此这意味着仅使用AB的“旧”代码可以完全更改其含义。取决于您的 header 是否包含在 header 之前,或者类似的操作。

    甚至在必须由两种类型之一声明转换的限制的情况下,要弄清楚发生错误时用户确切定义的转换顺序已经非常困难。如果您实际上必须完全搜索每个不相关的头文件,以找到这些转换函数定义,那么它会严重恶化维护问题,并且允许这样做似乎没有任何好处。我的意思是,您可以举一个非人为的示例,其中的语言功能可以帮助您简化或简化某些内容的实现吗?

    总的来说,我认为程序员喜欢这样的想法:要弄清一行a = b;的作用,他们只需要阅读a类型和b类型的定义,然后从那里去...如果您这样做,可能会很丑陋且痛苦开始允许更难了解的这些“陷阱”转换。

    我猜想就operator <<用于流而言,你可能会说同样的话...但是对于用户定义的转换来说,它会更加严重,因为它可能会影响该类型的对象作为参数传递的任何代码行。

  • 另外,我认为您不一定希望找到深思熟虑的原因,并不是标准允许编译器实现的所有可行方法。委员会倾向于保持保守并寻求共识,因此“没有人真正关心特性X足以为之奋斗”可能是一个很好的解释,就像您会发现为什么特性X不可用一样。

    Why is initialization of a constant dependent type in a template parameter list disallowed by the standard?

    对该问题的答案表明功能不可用的常见原因:

    1. Legacy: the feature was left out in the first place and now we've built a lot without it that it's almost forgotten (see partial function template specialization).

    关于c++ - 为什么我不能将C++转换运算符作为非成员函数重载于类之外?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34056443/

    相关文章:

    c++ - gcc 4.8 或更早版本是否存在关于正则表达式的问题?

    c++ - 如何使用模板修复 'no match for ‘operator*’(操作数类型为 ‘Matrix<double, 2, 3>’ 和 ‘Matrix<double, 3, 2>’)'

    c++ - 检测特定 C++ 类型是否有成员,排除继承的成员

    c++ - Google Protocol Buffers - 对 encode decode base64 char * c string Protocol Buffer 数据感到困惑

    c++ - 1 最终编译器错误 :( can someone explain in real simple for me

    c++ - 使用 std::for_each 并在 std::set 上绑定(bind)成员函数,代码无法编译

    c++ - 指针可以有不同的大小吗?

    android - Android 上的 C++11 std::chrono::steady_clock 问题

    c++ - 什么是 C++ 中的 ->* 运算符?

    operator-overloading - 如何在不进行子类化的情况下将运算符扩展添加为特定类的上下文的一部分?