为什么我不能在类外部作为非成员函数重载C++转换运算符?

8
这个问题似乎之前已经被问过,但我认为那个提问者在没有得到真正答案的情况下就匆忙地称某个答案为正确答案。也许没有具体原因,这需要后来加入标准中,你可以告诉我。 为什么不允许使用非成员函数重载C++转换运算符 我正在寻找当前标准设计中不允许此操作的具体原因。当您重载强制类型转换运算符以定义两种类型之间的隐式转换时,这个重载定义必须是您要转换的类的成员,而不是类外部的东西。显然的问题是,如果您有一些类型,由于某种原因您确实无法修改,但您希望为了语法的简单性(尽管存在隐式转换的缺陷)或因为您有一堆其他代码,标准或自定义依赖于隐式转换...如果您不能向类添加适当的隐式转换,则无法实现这样做,因此您需要使用像常规函数这样的转换工具,将其包装在本来应该是隐式转换方便性的周围。
此外,是否真的可能会存在在类外添加这些转换会有计算开销的情况?就我看来,编译器很容易在查找可用函数时将外部隐式转换函数与其转换的类相关联,以便代码在效率上像它是该类的一部分一样执行。唯一的缺点是它必须做一些额外的工作来进行初始关联,但这几乎不会有任何影响。
我不会接受“因为标准规定如此”或“因为隐式转换不好”作为答案。当他们撰写实际标准时,肯定有人有理由。
(我不是一个非常专业的人,我还在学习这门语言。)
编辑,回应: 我想情况可能是这样的,你修改了头文件,但你没有覆盖现有的头文件,因为那样会很糟糕。你会基于旧文件创建一个新的头文件来适应更改。假设旧代码已经编译成了目标文件,修改头文件只是告诉编译器有其他地方添加了额外的代码。它不会改变旧代码的功能,因为它已经编译过了,而且不依赖于它(例如某个供应商提供给你的目标代码和头文件)。如果我能修改和重新编译我将使用转换的代码,那么你就无法让我在外部编写转换函数了,我不会这样做,因为它太令人困惑了。你不必随机搜索每个头文件以寻找正确的定义;如果我自己编写代码,我会制作一个自定义头文件,其中包含我添加到供应商提供的头文件中的高可见性部分,并且该头文件与相关类型相关联,因此相对明显,而其他头文件将按其原始名称命名,这样你就知道它们没有更改。你还需要一个包含转换定义的相应文件,因此我的修改是自包含的,与原始目标代码分离,并且相对容易找到。当然,这是除了在代码中找出适用于哪个转换函数的实际难题之外的。我认为你可以找到各种情况,其中易于确定并且自然易用,因此将它们添加到现有库中以满足自己的目的是有意义的。如果我使用的是商业代码,我无法真正修改它,并且我看到自己的操作可以通过使用转换函数来与我的一些东西集成以改进它,那么我会考虑这样做。当然,这对于第三方只读a = b的人来说并不明显,他们不会知道我的转换正在发生什么,但如果你知道并且它表达得很好,那么它可能有效。
我感谢您关于标准决策如何运作的见解,这绝对是一种可以忽略的边缘问题。
1个回答

3
除了在类中具有非显式转换运算符,例如operator bool(),您还可以在您要转换的类中拥有接受单个参数的非显式构造函数,作为引入用户定义转换的一种方式。(问题中未提到)
至于为什么不能在不修改它们的定义的情况下介绍两种类型AB之间的用户定义转换......好吧,这将会创建混乱。
如果您可以这样做,则可以在头文件中执行此操作,并且由于引入新的用户定义转换可能会更改代码的含义,因此这意味着仅使用AB的“旧”代码可能会完全更改其所做的事情,具体取决于您的头文件是否在其之前被包含,或者诸如此类的事情。
即使限制转换必须由两种类型之一声明,弄清楚正在发生什么用户定义转换序列已经足够困难了。如果您必须在所有无关的头文件中完全搜索这些转换函数定义,那么维护问题就会大大恶化,而且似乎没有任何允许此功能的好处。我的意思是,您能否给出一个非人为的例子,说明这种语言特性如何帮助您使某些实现更简单或更易于阅读?
一般来说,我认为程序员们喜欢这个想法:要弄清楚一行a = b;的作用,他们只需要阅读a的类型定义和b的类型定义,然后从那里开始......如果您开始允许这些“陷阱”转换,则可能会非常丑陋和痛苦,因为它们很难知道。
我想你也可以用关于流的operator <<相同的话来说......但是对于用户定义的转换,情况更为严重,因为它可能会影响传递该类型对象作为参数的任何代码行。
此外,我不认为您必须期望找到一个经过深思熟虑的原因,编译器可以实现的不是标准允许的所有内容。委员会倾向于保守并寻求共识,因此“没有人真正关心X功能足以为其而战”可能是您将发现为什么X功能不可用的最好解释之一。 为什么标准不允许在模板参数列表中初始化常量相关类型? 对这个问题的答案提供了一个常见原因:
  1. 遗留问题:该功能一开始就被省略了,现在我们已经构建了很多没有它的东西,几乎被遗忘了(参见部分函数模板特化)。

我不太知道如何在评论区中进行长篇回复,因此我在顶部编辑了我的原始帖子。 - Lunarian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接