【问题标题】:Calling a const function rather than its non-const version调用 const 函数而不是其非 const 版本
【发布时间】:2011-11-09 08:47:19
【问题描述】:

为了我的目的,我尝试包装类似于 Qt 的共享数据指针的东西,经过测试,我发现应该调用 const 函数时,选择了它的非 const 版本。

我正在使用 C++0x 选项进行编译,这是一个最小的代码:

struct Data {
    int x() const {
        return 1;
    }
};

template <class T>
struct container
{
    container() {
        ptr = new T();
    }


    T & operator*() {
        puts("non const data ptr");
        return *ptr;
    }

    T * operator->() {
        puts("non const data ptr");
        return ptr;
    }

    const T & operator*() const {
        puts("const data ptr");
        return *ptr;
    }

    const T * operator->() const {
        puts("const data ptr");
        return ptr;
    }

    T* ptr;
};

typedef container<Data> testType;

void testing() {
    testType test;
    test->x();
}

如您所见,Data.x 是一个 const 函数,因此调用的运算符 -> 应该是 const 的。当我注释掉非常量时,它编译时没有错误,所以这是可能的。然而我的终端打印:

"非常量数据指针"

这是一个 GCC 错误(我有 4.5.2),还是我遗漏了什么?

【问题讨论】:

    标签: c++ operator-overloading constants overload-resolution const-method


    【解决方案1】:

    如果您有两个仅在 const-ness 上有所不同的重载,则编译器会根据 *this 是否为 const 来解析调用。在您的示例代码中,test 不是const,因此调用了非const 重载。

    如果你这样做了:

    testType test;
    const testType &test2 = test;
    test2->x();
    

    您应该看到另一个重载被调用,因为test2const

    【讨论】:

    • 所以如果对象没有声明为 const,编译器会更喜欢调用非 const 重载,即使它可以调用 const 重载?
    • @coyotte508:没错。非const 重载被认为是更好的匹配。
    • 从 C++20 开始你也可以这样做:testType test; std::as_const(test).x();
    【解决方案2】:

    test 是一个非常量对象,因此编译器会找到最佳匹配:非常量版本。您可以使用static_cast 应用常量:static_cast&lt;const testType&amp;&gt;(test)-&gt;x();

    编辑:顺便说一句,你怀疑 99.9% 的时间你认为你发现了一个编译器错误,你应该重新审视你的代码,因为可能有一些奇怪的怪癖,而编译器实际上是遵循标准的。

    【讨论】:

    • +1 表示“您可能没有在编译器中发现错误”评论
    【解决方案3】:

    Data::x 是否为常量函数并不重要。被调用的操作符属于container&lt;Data&gt;类而不是Data类,并且它的实例不是常量,所以调用了非常量操作符。如果只有常量运算符可用或者类的实例本身就是常量,那么常量运算符就会被调用。

    【讨论】:

      【解决方案4】:

      testType 不是 const 对象。

      因此它将调用其成员的非 const 版本。
      如果方法具有完全相同的参数,则必须选择调用哪个版本(因此它使用 this 参数(隐藏的参数))。在这种情况下,这不是 const,因此您将获得非常量方法。

      testType const test2;
      test2->x();  // This will call the const version
      

      这不会影响对 x() 的调用,因为您可以在非 const 对象上调用 const 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-17
        • 1970-01-01
        • 1970-01-01
        • 2013-05-17
        • 1970-01-01
        相关资源
        最近更新 更多