2011-09-02 42 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

相關問題