【问题标题】:Why is overriding both the global new operator and the class-specific operator not ambiguous behaviour?为什么同时覆盖全局 new 运算符和特定于类的运算符不是模棱两可的行为?
【发布时间】:2018-09-28 11:40:18
【问题描述】:

考虑以下代码:

class Foo 
{
public:
    //class-specific
    Foo operator+(Foo& rhs)
    {
       return Foo(); //Just return a temporary
    }

    void* operator new(size_t sd)
    {
        return malloc(sd);
    }
};

//global
Foo operator+(Foo& lhs, Foo& rhs)
{
    return Foo();
}

void* operator new(size_t sd)
{
    return malloc(sd);
}

此代码无法编译,说明调用不明确,因为它匹配两个运算符:

Foo a, b;
a + b;

但是这个带有 new 运算符的编译器很好,并且会调用特定于类的那个。

Foo* a = new Foo();

为什么不会导致编译错误?编译器是否以不同的方式对待 new 运算符? (任何对该标准的引用将不胜感激。)

【问题讨论】:

    标签: c++ c++11 c++14 language-lawyer new-operator


    【解决方案1】:

    为什么不会导致编译错误?编译器是否以不同的方式对待 new 运算符? (任何对标准的引用将不胜感激)

    关于全局new 和特定类new 之间的优先级,参考中提到this

    如分配函数中所述,C++ 程序可以为这些函数提供全局和类特定的替换。如果 new 表达式以可选的 :: 运算符开头,如 ::new T 或 ::new T[n],则将忽略特定于类的替换(在全局范围内查找函数)。 否则,如果 T 是类类型,则从 T 的类范围开始查找。

    因此特定于类的new 具有优先权。

    关于+ 的重载,您可以让成员重载 全局重载(通常作为类的friend)但不能同时使用,因为它会产生歧义。

    【讨论】:

      【解决方案2】:

      如果定义了类'operator new,则始终是首选:

      [expr.new]/9

      如果 new-expression 以一元 ​::​ 运算符开头,则在全局范围内查找分配函数的名称。否则,如果分配的类型是类类型T或其数组,则在T的范围内查找分配函数的名称。如果此查找找不到名称,或者分配的类型不是类类型,则在全局范围内查找分配函数的名称。

      阅读起来可能会很棘手:如果 new-expression 不是以 :: 开头并且 分配的类型 是类类型,那么 new 是在班级范围内查找。

      【讨论】:

        【解决方案3】:

        您的全局new 运算符与Foo 类没有直接关系。特定于类的new 优先于全局new。没有歧义。

        您的operator+ 确实与Foo 类特别相关。在外部定义的运算符和在类内部定义的运算符之间没有优先级。因此,您会变得模棱两可。

        【讨论】:

          猜你喜欢
          • 2012-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多