2013-08-28 38 views
0

考慮下面的代碼GCC-4.8.1爲什麼下面的代碼是錯誤(約重載決議)

struct Base 
{ 
}; 

struct Derive : private Base 
{ 
}; 

void fn(Base, int); 

struct Conv 
{ 
    operator Base() const; 
    operator Derive(); 
}; 

int main() 
{ 
    Conv c; 
    fn(c, 0); 
    return 0; 
} 

當我給上面的代碼中,我得到了一個error.I認爲編譯器將選擇Conv::operator Base()但實際上編譯器選擇Conv::operator Derive()

但是,當我把下面的代碼,編譯器選擇Conv::operator Base()

struct Base 
{ 
}; 

struct Derive// : private Base 
{ 
}; 

void fn(Base, int); 

struct Conv 
{ 
    operator Base() const; 
    operator Derive(); 
}; 

int main() 
{ 
    Conv c; 
    fn(c, 0); 
    return 0; 
} 
+0

爲什麼你認爲編譯器應該選擇'Base'在這種情況下(C是不是'const')?這是相當多了'is_base_of'招 – nijansen

+1

其實,這裏有一個詳細的解釋:http://stackoverflow.com/a/2913870/1056003 – nijansen

回答

2

的關鍵是,直到選擇了轉換序列訪問說明不檢查,所以代碼感覺像:

struct base {}; 
struct derived : base {}; 
struct conv { 
    operator base() const; 
    operator derived(); 
}; 
void fn(base); 
int main() { 
    conv c; 
    fn(c); 
} 

在這一點上有不同的有效轉換序列:

  • 加入const資格,然後用戶轉換爲基地
  • 用戶轉換爲派生,派生到基地轉換

第二次轉換是一個更好的轉換序列,它被選中。

這在標準處理中13.3.3.1/2:

隱式轉換序列只關心的類型,CV-資格,和參數的值類別和這些如何被轉換以匹配參數的相應屬性。其他屬性,如生存期,存儲類,對齊方式或參數的可訪問性以及參數是否爲位字段將被忽略。所以,雖然的隱式轉換的序列可以爲一個給定的參數參數對來定義,從參數於該參數的轉換可能仍形成不良,歸根到底

4

c對象是非const的,所以在第一種情況下,Derive重載是一個精確的const-correct匹配,仍然可以隱式轉換爲Base。在第二個示例中,Derive無法轉換爲Base,因此必須選擇直接Base轉換。

+0

但是'Base'是私有的,'Derive'似乎沒有轉化爲'Base' 。 – miskcoo

+1

@ user2482012:此時不檢查訪問說明符。只有在選擇了轉換序列後,訪問說明符纔會起作用。我在答案中添加了具體的引用(13.3.3.1/2)。 –