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

2024-01-07

这个问题以前曾被问过,但我觉得提问者在从未真正得到真正答案的情况下匆忙地认为答案是正确的。也许没有什么原因,这需要稍后纳入标准,你告诉我。不允许使用非成员函数重载 C++ 转换运算符的理由是什么 https://stackoverflow.com/questions/2733459/what-is-the-rationale-to-not-allow-overloading-of-c-conversions-operator-with

我正在寻找当前标准设计中不允许这样做的具体原因。基本上,当您重载强制转换运算符以定义两种类型之间的隐式转换时,此重载定义必须是要转换的类的成员,而不是类外部的成员。明显的问题是,如果你有一些类型,由于某种原因你确实无法修改,但你想在它们之间隐式转换,以便语法简单(尽管隐式转换有弊端),或者因为你有一堆其他类型依赖于隐式转换的代码、标准或自定义...如果您无法向类添加适当的隐式转换,您就无法做到这一点,因此您需要使用诸如常规函数之类的变通方法来进行转换,您可以将其包装起来否则是为了隐式转换的方便。

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

我不会将“因为标准是这么说的”或“因为隐式转换不好”作为答案。有人在编写实际标准时肯定是有原因的。

(我不是一个大专家,我仍在学习这门语言。)

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

我很欣赏关于标准决策如何运作的见解,这绝对是一种你可以忽略的边缘事物。


  1. 除了具有非显式转换运算符之外,例如operator bool()在类中,您还可以在要转换的类中使用带有单个参数的非显式构造函数to,作为引入用户定义转换的一种方式。 (问题中没有提到)

  2. 至于为什么不能在两种类型之间引入用户定义的转换A and B不修改它们的定义...这会造成混乱。

    如果你能做到这一点,那么你可以在头文件中做到这一点,并且由于引入新的用户定义的转换可以改变代码的含义,这意味着“旧”代码仅使用A and B可以完全改变它正在做什么,具体取决于您的标头是否包含在它之前,或者类似的东西。

    即使存在转换必须由两种类型之一声明的限制,在出现问题时准确弄清楚正在发生什么用户定义的转换序列已经足够困难了。如果您确实必须完整地搜索每个不相关的头文件才能找到这些转换函数定义,那么这会极大地恶化维护问题,并且允许这样做似乎没有任何好处。我的意思是,您能否举一个非人为的示例,其中该语言功能可以帮助您使某些内容的实现变得更简单或更易于阅读?

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

    我想你也可以对以下方面说同样的话operator <<用于流媒体...但对于用户定义的转换,情况会更加严重,因为它可能会影响any该类型的对象作为参数传递的代码行。

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

为什么标准不允许在模板参数列表中初始化常量相关类型? https://stackoverflow.com/questions/32104890/why-is-initialization-of-a-constant-dependent-type-in-a-template-parameter-list

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

  1. 遗留问题:该功能一开始就被遗漏了,现在我们已经构建了很多没有它的功能,以至于它几乎被遗忘了(请参阅部分功能模板专业化)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐