【问题标题】:Why can't I overload C++ conversion operators outside a class, as a non-member function?为什么我不能在类之外重载 C++ 转换运算符,作为非成员函数?
【发布时间】:2016-03-07 12:04:27
【问题描述】:

以前有人问过这个问题,但我觉得提问者在没有真正得到真正答案的情况下匆忙称答案正确。也许没有原因,这需要稍后放入标准中,你告诉我。 What is the rationale to not allow overloading of C++ conversions operator with non-member functions

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

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:
    1. 除了具有非显式转换运算符,例如operator bool() 在一个类中,您还可以在要转换 的类中使用带有单个参数的非显式构造函数,作为引入用户定义转换的一种方式。 (未提及)

    2. 至于为什么不能在不修改定义的情况下在AB 两种类型之间引入用户定义的转换……这会造成混乱。

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

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

      总的来说,我认为程序员喜欢这样的想法,即要弄清楚一行 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. 遗留:该功能一开始就被遗漏了,现在我们已经构建了很多没有它的东西,几乎被遗忘了(请参阅部分功能模板专业化)。

    【讨论】:

    • 我真的不知道如何在 cmets 部分给出长回复,所以我在顶部编辑了我的原始帖子
    猜你喜欢
    • 2017-07-16
    • 2012-02-01
    • 1970-01-01
    • 2010-12-26
    • 2015-11-13
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多