class Test
{
public:
operator Test * () { return NULL; };
};
int main()
{
Test test;
if (test == NULL)
printf("Wtf happened here?\n");
return 0;
}
这段代码为什么能编译通过?Test类从何得到比较操作符?是否存在一些隐式转换?那个重载的操作符具体意义是什么(并且会做些什么)?
class Test
{
public:
operator Test * () { return NULL; };
};
int main()
{
Test test;
if (test == NULL)
printf("Wtf happened here?\n");
return 0;
}
这段代码为什么能编译通过?Test类从何得到比较操作符?是否存在一些隐式转换?那个重载的操作符具体意义是什么(并且会做些什么)?
重载运算符添加了从 Test
到 Test *
的转换。由于没有定义接受 Test
和 NULL
作为参数的比较运算符,因此任何已存在的转换运算符都会被尝试。 operator Test *
返回一个可与 NULL
进行比较的类型,因此被使用。
是的,你已经添加了一个对 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.
// ...
}
*
暴露包装对象的某个实例,那么也许你应该重载->
而不是重载*
。class Bar
{
public:
void Baz() { ... }
}
class Foo
{
private:
Bar* _bar;
public:
Bar* operator -> () { return _bar; }
}
// call like this:
Foo f;
f->Baz();
只是一个想法。