2014-09-23 82 views
30

由於char的隱式轉換,下面的代碼編譯。我不知道爲什麼,因爲我期望(並期望失敗)的唯一隱式轉換是從char const*size_tC++意外暗示轉換

#include <cstddef> 

struct foo 
{ 
    int operator[](size_t i) const { return 1; } 
    operator char() const { return 'a'; } 
}; 

int main() 
{ 
    foo f; 
    f["hello"]; // compilation error desired here 
} 

這是什麼隱式轉換允許這個編譯?如果我刪除operator char或使它explicit然後編譯失敗在所需的位置。

該代碼從中提取的類確實需要隱式轉換和operator[]。那麼有沒有一種方法可以在不明確轉換的情況下防止行爲?

+1

您是否嘗試過加入一個私有的'operator [](char const *)'? – 2014-09-23 06:15:45

回答

34

行編譯的原因是,通過隱式轉換,可以將其重新解釋爲'a'["hello"];,這又與編寫*(('a')+("hello"));也編譯相同。

摘錄爲標準:

5.2.1下標:

...該 表達E1 [E2]是相同的(根據定義)爲*((E1)+(E2) )...

未做轉換操作符明確,最簡單的解決方法是申報違規標操作爲刪除:

struct foo 
{ 
    operator char() const { return 'a'; } 
    int operator[](size_t i) const { return 1; } 

    // prevent accidental use of foo["hello"] 
    int operator[](char const*) const = delete; 
}; 
+3

...以及相當於'*(E2 + E1)'和'E2 [E1]'的交換性?我不會說那麼明顯...... – 2014-09-23 06:14:44

+7

@UlrichEckhardt,是的,''你好「[0]'相當於'0 [」hello「]'。 – imreal 2014-09-23 06:18:42

+4

確實,這並不明顯。這是C++。有充滿C++陷阱和陷阱的書籍。 – Jerry101 2014-09-23 06:48:28

0
f["hello"]; 

轉換爲f.operator [](index),其中index是指向「hello」的指針的值。在你的情況下,它調用operator [](size_t i)。因此,編譯器絕對沒有抱怨。事實上,指數值將是人; ARGE值(一個指針的值),所以最好同時超載[]要小心,並檢查上邊界有 事實上,如果您有:

char *c = "hello"; // c is a pointer 
f[c]; // ok 
+0

嗯,這是完全錯誤的和誤導性的,'char *'不能隱式轉換爲'size_t',所以'foo :: operator []'永遠不會被選中,而是'f '轉換爲'char',以便轉換爲''a'[「hello」]',它與''hello'['a']'相同,在ascii中是''hello「[97]'請在發佈之前查看已被接受的答案。 – marack 2014-09-25 22:32:50