【问题标题】:Consequences of overloading the conversion operator重载转换运算符的后果
【发布时间】:2015-04-14 11:27:04
【问题描述】:

我有一个带有这样的重载转换运算符的类:

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

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

【问题讨论】:

  • 顺便说一句,使构造函数explicit 会导致pointer = pointer + 1; 失败。

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


【解决方案1】:

上面的一些操作是有效的,因为编译器可以将自定义类型:Pointer&lt;MyClass&gt; 转换为原始指针:MyClass* 隐式使用 SINGLE 用户定义的转换。 隐式转换有严格的规则,描述为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 == &amp;my_object) { /* ... */ } // works

  • 情况(2),间接(operator*)采用可以隐式转换为MyClass*的操作数,然后是结构引用(operator.):

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

  • 不匹配任何情况,operator-&gt; 不接受任何可以隐式转换的参数:

    pointer-&gt;some_method (); // doesn't work

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

    pointer = pointer + 1; // works

  • 不匹配任何情况;请注意,即使显式转换为MyClass*(例如static_cast&lt;MyClass*&gt;(pointer)++)也无济于事,因为这里需要左值;解决方法是:auto ptr = &amp;(*pointer); ptr++;

    pointer++; // doesn't work

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

【讨论】:

  • 为什么pointer-&gt;some_method (); 需要不止一次的隐式转换? pointer 可以转换为 T* 应该足以让操作员工作
  • operator-&gt; 添加到Pointer 类有助于:T* operator-&gt;() { return object; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多