2011-09-02 44 views
19

我试着包装一些类似于Qt的共享数据指针,以达到我的目的,并且在测试后,我发现当const函数应该被调用时,它的非const版本是改为选择。调用一个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函数的时候,它编译没有错误,所以它是可能的。然而,我的终端打印:

“非const的数据PTR”

它是一个GCC的bug(我有4.5.2),或者是有什么我失踪?

回答

17

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

如果你这样做:

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

你应该看到的是,其他的过载被调用,因为test2const

+2

所以如果对象没有声明为const,编译器会更喜欢调用非const重载,即使它可以调用const重载? – coyotte508

+2

@ coyotte508:正确。非'const'超载被认为是更好的匹配。 –

1

但是testType不是一个const对象。

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

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

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

2

Data::x是否为常数函数并不重要。被调用的操作符属于​​类,而不属于Data类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用,或者类的实例本身是常量,则会调用常量运算符。

4

test是一个非const对象,所以编译器找到最佳匹配:非const的版本。您可以将常量性与static_cast虽然:static_cast<const testType&>(test)->x();

编辑:顺便说一句,当你怀疑你认为你已经找到了一个编译器错误,你应该重新审视你的代码可能有一些奇怪的怪癖和编译器99.9%的时间其实是遵循这个标准的。

+0

对于“你可能没有在编译器中发现错误”的评论+1 – MikMik

相关问题