转换运算符重载的后果

时间:2015-04-14 11:27:05

标签: c++ operator-overloading implicit-conversion

我有一个带有重载转换运算符的类,如下所示:

template <class T> class Pointer {
    T* object;
public:
    Pointer (T* object): object(object) {}
    operator T* () { return object; }
};

我注意到我现在通常需要手动重载的一些操作员突然工作,好像PointerT*但是有些操作员没有:

MyClass my_object;
Pointer<MyClass> pointer (&my_object);
if (pointer) { /* ... */ } // works
if (pointer == &my_object) { /* ... */ } // works
(*pointer).some_method (); // works
pointer->some_method (); // doesn't work
pointer = pointer + 1; // works
pointer++; // doesn't work

根据标准假设这是正确的行为,我怎么知道哪些有效,哪些无效(没有试验和错误),更重要的是,为什么会这样?

1 个答案:

答案 0 :(得分:0)

上述某些操作有效,因为编译器可以使用SINGLE用户定义的转换隐式地将自定义类型:Pointer<MyClass>转换为原始指针:MyClass*。 隐式转换有严格的规则,描述为here

  

只要某种类型的表达式执行隐式转换   T1用于不接受该类型的上下文中,但接受一些   其他类型T2,特别是:

(1) When the expression is used as the argument when calling a function that is declared with T2 as parameter.
(2) When the expression is used as an operand with an operator that expects T2
(3) When initializing a new object of type T2, including return statement in a function returning T2.
(4) When the expression is used in a switch statement (T2 is integral type)
(5) When the expression is used in an if statement or a loop (T2 is bool)

上面的一些调查例子,如果有人可以验证或纠正我的扣除,我将不胜感激。

  • 案例(5),if陈述:

    if (pointer) { /* ... */ } // works

  • case(2),operator==带有操作数,可以隐式转换为MyClass*

    if (pointer == &my_object) { /* ... */ } // works

  • case(2),indirection(operator*)取操作数,可以隐式转换为MyClass*,然后是结构引用(operator.):

    (*pointer).some_method (); // works

  • 与任何情况都不匹配,operator->不接受任何可以隐式转换的参数:

    pointer->some_method (); // doesn't work

  • case(2):operator+采用可隐式转换为MyClass*的操作数,并使用构造函数和Pointer<MyClass>将返回值赋给operator=;请注意,向构造函数添加explicit会阻止编译,因为表达式的返回类型:pointer + 1MyClass*,因此隐式调用构造函数MyClass*

    pointer = pointer + 1; // works

  • 与任何案件都不匹配;请注意,即使明确转换为MyClass*(例如static_cast<MyClass*>(pointer)++)也无济于事,因为此处需要左值;解决方法是:auto ptr = &(*pointer); ptr++;

    pointer++; // doesn't work

请记住,重载转换操作符有时会导致危险情况,例如。 MyClass* ptr = pointer; delete ptr;将删除底层资源,编译器甚至不会抱怨。