重载运算符"operator T * ()"会生成一个比较运算符吗?

4
class Test
{
public:
    operator Test * () { return NULL; };
};

int main()
{
    Test test;
    if (test == NULL)
        printf("Wtf happened here?\n");

    return 0;
}

这段代码为什么能编译通过?Test类从何得到比较操作符?是否存在一些隐式转换?那个重载的操作符具体意义是什么(并且会做些什么)?

4个回答

7

重载运算符添加了从 TestTest * 的转换。由于没有定义接受 TestNULL 作为参数的比较运算符,因此任何已存在的转换运算符都会被尝试。 operator Test * 返回一个可与 NULL 进行比较的类型,因此被使用。


NULL是一种特殊的东西吗?我认为它总是被定义为0,而不是一个特殊的指针。 - Oliver Zheng
在C++中,NULL等同于0,但整型字面值0是一个特殊情况。它可以转换为任何指针类型。 - Baffe Boyois

1

是的,你已经添加了一个对 T* 的隐式转换,因此编译器将使用它来与 NULL 进行比较。

还有几件事情需要注意:

NULL 是 0 的简写,因此允许与 0 进行比较。(然而,对于其他整数值,这并不成立。0 是特殊的。)

你的类型也可以在布尔上下文中隐式使用。也就是说,这是合法的:

Test test;
if (test)
{
    // ...
}

C++0x允许您指定一个explicit关键字来禁止转换运算符进行此类操作。

隐式转换为指针类型通常相当可疑。除了在意外情况下发生转换的陷阱之外,如果对象拥有返回的指针,则可以允许危险的情况发生。例如,考虑一个允许隐式转换为const char*的字符串类:

BadString ReturnAString();

int main()
{
    const char* s = ReturnAString();
    // Uh-oh.  s is now pointing to freed memory.

    // ...
}

0
Baffe的回答值得一加。如果你想以某种方式通过*暴露包装对象的某个实例,那么也许你应该重载->而不是重载*
class Bar
{
public:
   void Baz() { ... }
}

class Foo
{
private:
    Bar* _bar;
public:
    Bar* operator -> () { return _bar; }
}

// call like this:
Foo f;
f->Baz();

只是一个想法。


-3

你还没有定义自己的比较函数,因此编译器已经为你完成了一个。但是你尝试重载解引用运算符...我不知道为什么要这样做。

你需要定义自己的 operator== 函数

阅读this


2
这绝对不是正在发生的事情。operator==没有默认定义。而且他也没有重载解引用运算符。 - Benjamin Lindley

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