Lu*_*ian 6 c++ standards operator-overloading c++11
这个问题以前有人问过,但我觉得提问者在他从未真正得到真正的答案时匆忙地认为答案是正确的。可能没有什么原因,这个需要以后放到标准里,你告诉我。 不允许使用非成员函数重载 C++ 转换运算符的理由是什么
我正在寻找不允许将其作为当前标准设计的一部分的具体原因。基本上,当您重载强制转换运算符以定义两种类型之间的隐式转换时,此重载定义必须是您正在转换的类的成员,而不是类之外的东西。显而易见的问题是,如果您有类型由于某种原因确实无法修改,但为了语法的简单性(尽管隐式转换的缺点)或因为您有一堆其他依赖于隐式转换的代码、标准或自定义……如果您不能向类添加适当的隐式转换,则不能这样做,
另外,在类之外添加这些转换是否真的可能存在计算开销?在我看来,编译器很容易在弄清楚哪些函数可用时,将外部隐式转换函数与它们转换的类相关联,以便代码像它是该类的一部分一样执行就效率而言。唯一的缺点是它必须做一些额外的工作来建立初始关联,这应该几乎没有。
我不会将“因为标准这么说”或“因为隐式转换不好”作为答案。有人在编写实际标准时肯定有理由。
(我不是一个大专家,我还在学习这门语言。)
编辑,回复:嗯,我想情况可能是这样,是的,您更改了头文件,但是您不做的是覆盖现有的,因为那会很糟糕。您将根据旧的头文件创建一个新的头文件以适应更改。假设是旧代码已经在目标文件中编译,并且更改标头只会告诉编译器您在其他地方添加了其他代码。它不会改变旧代码的作用,因为它已经编译并且不依赖于它(即某些供应商交给您目标代码和标头)。如果我可以修改和重新编译我将使用转换的代码,那么你不能让我在外部编写转换函数,我不会这样做,这太混乱了。你不会 不必随机搜索每个标题以获得正确的定义;如果我自己编写代码,我会制作一个带有高度可见部分的自定义标头,其中我添加到供应商提供的标头中的内容是,并且所述标头对于它是哪个相对明显,因为它将与相关类型和其他标题将以其原始名称命名,因此您会知道它们没有更改。并且您将有一个仅包含转换定义的相应文件,因此我的修改将是独立的,与原始目标代码分开,并且相对容易找到。当然,这不包括在代码中找出应用哪个转换函数的实际努力。我想你可以找到各种各样的情况,“ 很容易确定,也很自然,可以在适合您自己的目的添加到这样的现有库中的地方使用。如果我使用的是我无法真正修改的商业代码,并且我看到可以通过使用转换函数将其与我自己的一些东西集成来改进我正在做的事情,我可以看到自己想要做的这个。当然,对于仅阅读 a = b 的第三人来说,这些事情并不明显,他们不会知道我的转换发生了什么,但是如果你知道并且读起来很好,那么它就可以工作。t 真的修改,我看到了一种情况,我可以通过使用转换函数将它与我自己的一些东西集成来改进我正在做的事情,我可以看到自己想要这样做。当然,对于仅阅读 a = b 的第三人来说,这些事情并不明显,他们不会知道我的转换发生了什么,但是如果你知道并且读起来很好,那么它就可以工作。t 真的修改,我看到了一种情况,我可以通过使用转换函数将它与我自己的一些东西集成来改进我正在做的事情,我可以看到自己想要这样做。当然,对于仅阅读 a = b 的第三人来说,这些事情并不明显,他们不会知道我的转换发生了什么,但是如果你知道并且读起来很好,那么它就可以工作。
我很欣赏关于标准决策如何运作的洞察力,这绝对是一种你可以忽略的边缘事物。
除了在类中使用非显式转换运算符之外,您还可以在要转换为的operator bool()类中使用采用单个参数的非显式构造函数,作为引入用户定义转换的一种方式。(问题中没有提到)
至于为什么不能在两种类型之间引入用户定义的转换A而不B修改它们的定义......这会造成混乱。
如果你能做到这一点,那么你可以在头文件中做到这一点,并且由于引入新的用户定义的转换可以改变代码的含义,这意味着“旧”代码仅使用AandB可以完全改变它正在做的事情,具体取决于如果你的标题包含在它之前,或者类似的东西。
即使存在转换必须由两种类型之一声明的限制,在出现问题时准确地弄清楚正在发生什么用户定义的转换序列已经足够困难了。如果您确实必须完整地搜索每个不相关的头文件才能找到这些转换函数定义,那么这会极大地恶化维护问题,并且允许这样做似乎没有任何好处。我的意思是,您能否举一个非人为的示例,其中该语言功能可以帮助您使某些内容的实现变得更简单或更易于阅读?
一般来说,我认为程序员喜欢这样的想法:要弄清楚一行的作用,他们只需要阅读 的类型和 的类型a = b;的定义,然后从那里开始......如果你开始允许这些,它可能是丑陋和痛苦的更难了解的“陷阱”转换。ab
我想对于operator <<用于流式传输,您可能会说同样的事情......但是对于用户定义的转换,情况会更加严重,因为它可能会影响将该类型的对象作为参数传递的任何代码行。
另外,我认为您不一定应该期望找到一个经过深思熟虑的原因,并非标准允许编译器实现的所有可行的内容。委员会倾向于保守并寻求共识,因此“没有人真正关心 X 功能并为之奋斗”可能是一个很好的解释,因为您会发现为什么功能 X 不可用。
该问题的答案表明了功能不可用的常见原因:
- 遗留问题:该功能一开始就被遗漏了,现在我们已经构建了很多没有它的功能,以至于它几乎被遗忘了(请参阅部分功能模板专业化)。