2012-07-04 63 views
7

我是否在5.2.8.3: ... If the type of the expression is a class type, the class shall be completely-defined.中正確讀取標準如果類型不是「完全定義」,那麼這是否意味着下面的程序是未定義的?在前向聲明類型未定義行爲上使用typeid?

Foo.cpp中:

struct foo 
{ 
    virtual void a(){} 
}; 

struct bar : foo 
{ 
    virtual void a(){} 
}; 

bar abar; 

foo& get_some_foo() 
{ 
    return abar; 
} 

main.cpp中:

#include <iostream> 
#include <typeinfo> 

struct foo; 

foo& get_some_foo(); 

int main() 
{ 
    foo& a_ref_foo(get_some_foo()); 

    std::cout << "a_ref_foo typeid name: " << typeid(a_ref_foo).name() << std::endl; 

    return 0; 
} 

MSVC10輸出:`a_ref_foo typeid的名字:結構富」

回答

10

當我和編譯代碼:

g++ foo.cpp main.cpp -o main 

我得到:

main.cpp: In function ‘int main()’: 
main.cpp:12:52: error: invalid use of incomplete type ‘struct foo’ 
main.cpp:4:8: error: forward declaration of ‘struct foo’ 

與我的標準的解釋一致,就可以不適用typeid不完全類型 - 和a_ref_foo是不完整的類型,因爲類型foo的完整定義不可見。 main.cpp(與我添加的行)格式不正確,需要診斷。

更新:

我轉載使用Visual Studio 2010 Express中的問題。即使禁用了語言擴展名,這個簡單的程序:

#include <typeinfo> 

struct foo; 

int main() 
{ 
    typeid (foo); 
    return 0; 
} 

編譯時沒有診斷消息。用GCC 4.7,我得到:

main.cpp: In function ‘int main()’: 
main.cpp:7:14: error: invalid use of incomplete type ‘struct foo’ 
main.cpp:3:8: error: forward declaration of ‘struct foo’ 

同樣的規則:

如果表達式的類型是一個類類型,該類應 完全定義。

出現在1998,2003和2012版的ISO C++標準中。

看起來像在Visual Studio中的錯誤。 (如果有人想向微軟報告,請繼續。)

+4

在這種情況下,使用「shall」意味着它是不合格的,因爲這是一個可診斷的規則(即,並不是說「不需要診斷」並且沒有明確描述爲未定義的行爲)。 –

+0

@ R.MartinhoFernandes:謝謝,我已經更新了答案。 (我更熟悉的C標準使用「應」不同;違反「不應該」在明確的*約束下*使程序的行爲不確定C++規則在第1.4節「執行合規「。) –

+0

你對包含的假設是正確的。對於那個很抱歉。我也只是嘗試了gcc並得到了相同的錯誤。它有趣的MSVC 10與W4甚至沒有警告。 – Zac

0

你的程序是完全正確的,因爲功能get_some_foobar是全局變量。所以bar是完全定義的,但如果在main.cpp中定義bar的變體,則將其用作typeid中的參數,否則在編譯時發生錯誤。

+0

在定義了'main'的翻譯單元中,類型'foo' **是**不完整的。 –

5

是的,程序是不合格的(而不是導致未定義的行爲)。

如果你想知道爲什麼,那麼你應該考慮typeid是一個單一的運營商,但它具有多態類型比非多態類型完全不同的語義。特別是,如果foo是多態的(具有至少一個虛擬函數,那麼typeid將產生於type_info對象爲實際類型(在這種情況下bar基準),而如果類型不具有任何虛擬函數,那麼它會返回到type_info對象爲靜態型表達的引用(在這種情況下foo)。

對於編譯器生成適當的代碼,編譯器必須知道在其中使用typeid地點中在這兩種情況下適用,如果類型不完整,則該信息不存在編譯器。

+0

你是爲什麼有道理 - 那是我所假設的,編譯器只看到一個非多態類型。我遇到了這種行爲,並且正在深入研究標準,試圖找出它的含義。謝謝。 – Zac

+0

@Zac:編譯器應該拒絕你的代碼。它不是未定義的行爲,而是一種由編譯器輕易診斷的不合格程序。 –

+0

這種區別(動態與靜態類型)不適用於typeid的使用,其中參數是類型名稱,GCC至少也會標記爲錯誤,例如:struct Foo; const std :: type_info&fooType = typeid(Foo); –

相關問題