调用const函数而不是非const版本

时间:2011-09-02 17:22:09

标签: c++ const

我试图为我的目的包装类似于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函数,因此运算符 - &gt;被叫应该是常数。当我注释掉非常量的那个时,它编译没有错误,所以它是可能的。然而我的终端打印:

  

“non const data ptr”

这是一个GCC错误(我有4.5.2),还是有什么我想念的?

4 个答案:

答案 0 :(得分:24)

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

如果你这样做了:

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

你应该看到调用了另一个重载,因为test2const

答案 1 :(得分:9)

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

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

答案 2 :(得分:2)

Data::x是否是常数函数并不重要。被调用的运算符属于container<Data>类而不是Data类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用或者类的实例本身是常量,那么就会调用常量运算符。

答案 3 :(得分:0)

但是testType不是const对象。

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

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

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