2012-06-20 43 views
18

我希望標題實際上描述了什麼我想問問...C++方法調用和類型範圍分辨率歧義

我寫了一張與GCC編譯和工程,我預期的代碼。但是,它不會用llvm進行編譯,並且在使用icc編譯時代碼的執行方式會有所不同!
這是問題的一個例子:

#include <iostream> 

using std::cout; using std::endl; 

class A { 
public: 
    virtual void foo() { cout << "A::foo()" << endl; } 
}; 

class B : public A { 
public: 
    typedef A base; 
    virtual void foo() { cout << "B::foo()" << endl; } 
}; 

int main() { 
    typedef B base; 
    base* bp = new B(); 
    bp->base::foo(); 
} 

GCC輸出:A :: foo的()
ICC輸出:B :: foo的()

有人能解釋一下什麼是標準說一下這個案例?

+5

我想說這是GCC和ICC中的一個錯誤,因爲'B :: base'不是''B''的_member_,這意味着它不可能作爲一個成員來訪問它('bp-> base')。 –

+1

我同意@JoachimPileborg,而且在這個範圍內'base'可以被解釋爲B.你有警告標誌編譯? (-gall for gcc) – Geoffroy

+1

這不就是未定義的行爲,因爲'main'不是必需的形式嗎?看起來所有的編譯器都是正確的。 –

回答

7

從C++ 11,§3.4.5/ 4:

如果類成員訪問中的id表達式是 表
 
    class-name-or-namespace-name::... 
的限定標識,則類名或命名空間名稱 後面的。或 - >運算符首先在 對象表達式的類中查找,並使用名稱(如果找到)。否則,在整個postfix-expression的上下文中查找 。

我不認爲它可以更清楚。這找到B::base,所以輸出 應該是A::foo()

+0

謝謝你的幫助,你們真棒。這個特定的段落確實非常清楚並且恰到好處! – Nowakus

6

我認爲該標準的這部分是相關的:

3.4.3.1類成員[class.qual]

1)如果一個合格-ID的嵌套名稱說明符提名一個類,除了下面列出的情況外,在類(10.2), 的範圍內查找 嵌套名稱指定符後指定的名稱。該名稱應代表該類或其基類之一(第10條)的一個或多個其他成員。 [注意:可以在任何 點的潛在範圍(3.3.7)中使用合格標識符引用班級成員。結束註釋] 上述名稱查找規則的例外如下:

- 析構函數名稱爲 按照3.4.3中的規定查找;

- conversion-type-id的轉換類型id在類成員訪問(見3.4.5)中以與 conversion-type-id相同的方式查找;

- 在模板ID的模板參數中的名稱 在整個後綴表達式發生的上下文 中查找。

- 在使用聲明(7.3.3)中指定的名稱 的查找也找到隱藏在相同範圍(3.3.10)中的枚舉類名或 枚舉名。

base::在這種情況下,似乎「提名」了一個班級,所以查找是在班級範圍內完成的。我看不出任何異常情況如何適用,因此這是該類的範圍,因爲base等於A

(5.1.1-8表示它是一個合格的-ID在這種情況下,並且3.4.3.1內)

+0

同意。這對我來說似乎也很清楚。代碼是正確的,定義良好,輸出應該是'A :: foo'。 –