【问题标题】:When overloading operators in C++ why is T* preferred over bool?在 C++ 中重载运算符时,为什么 T* 优于 bool?
【发布时间】:2020-03-03 23:01:45
【问题描述】:

我有一个包装类,它的行为应该像一个指针。我已经超载了operator T*operator bool。 Bool 做了一些额外的验证。 我尝试在 if 中使用该对象,但我注意到调用的是 operator T* 而不是 bool。有人可以解释我为什么吗?这是在标准中以某种方式指定的吗?我在 MSVC、clang 和 gcc 中测试了下面的示例代码,它们都调用operator T*。 另外,根据我在此页面上阅读的内容 (https://en.cppreference.com/w/cpp/language/implicit_conversion),if 应该尝试转换为 bool

#include <stdio.h>

class MyClass
{
public:
    MyClass(int i)
        : m(i)
    {}

    operator bool() const
    {
        printf("operator bool()\n");
        return m;
    }

    operator int* ()
    {
        printf("operator int* ()\n");
        return &m;
    }

private:
    int m;
};

int main()
{
    MyClass a(5);
    MyClass b(0);

    if (a)
        printf("a is true\n");
    else
        printf("a is false\n");

    if (b)
        printf("b is true\n");
    else
        printf("b is false\n");

    return 0;
}

PS:我也试过!!(bool),但它仍然调用operator int*()。对于operator bool(),我必须明确地调用它。

【问题讨论】:

  • 在链接中跳到安全布尔问题部分。

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


【解决方案1】:

在您的类定义中,转换运算符 operator bool 使用限定符 const 声明,但 if 语句中使用的对象不是常量对象。

operator bool() const
                ^^^^^
{
    printf("operator bool()\n");
    return m;
}

删除限定符const,将调用运算符operator bool

或者声明转换运算符operator int *like

operator const int* () const
{
    printf("operator int* ()\n");
    return &m;
}

将再次调用运算符operator bool

当运算符具有限定符 const 并应用于非常量对象时,需要再进行一次转换,即限定转换。

此外,您甚至可以将运算符声明为显式。例如

explicit operator bool() 
{
    printf("operator bool()\n");
    return m;
}

【讨论】:

  • 详细说明:非常量成员函数在重载决议中获胜,因为它比 const 成员函数需要更少的转换。
  • @VladfromMoscow 非常感谢您的快速回复和澄清! “当运算符具有限定符 const 并应用于非常量对象时,需要再进行一次转换,即限定转换。”这就是我所缺少的:)
  • @RaduC 此转换应用于隐式参数 this。
【解决方案2】:

我想你可以在标准中找到具体的措辞。或this proposal

但我想说你想要的是explicit operator bool()

【讨论】:

【解决方案3】:

如果你想看看如何自己得出弗拉德的(正确)答案,过程大致是

  1. if statement

    条件是一个可以根据上下文转换为布尔值的表达式

  2. Contextual conversions 属于隐式转换 - 特别注意

    如果被调用的函数或运算符有多个重载,则在构建从 T1 到每个可用 T2 的隐式转换序列后,重载决策规则决定编译哪个重载。

    然后在转换顺序下,第三步“零或一个标准转换序列”在自定义转换之后,这一步可以将指针转换为bool。 p>

    这意味着两个用户定义的转换运算符都适用于该序列的中间步骤。最后,

  3. Overload resolution

    描述了如何选择最佳可行的功能。由于这两个运算符在转换序列的中间步骤的上下文中都是可行的,因此在 this 之后发生的额外指针到布尔转换不会对重载排名产生影响。

    具体来说,排名是基于这样一个事实:一个运算符需要对其隐式第一个 (this) 参数进行 const 限定,而另一个则不需要。这就是为什么同一运算符的一对 const 和非 const 限定的重载将始终选择其限定最接近被调用的对象的重载。

【讨论】:

    猜你喜欢
    • 2010-11-23
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多