c++ - struct用法 - typedef struct struct




C++中'struct'和'typedef struct'的區別? (6)

在C ++中,是否有任何區別:

struct Foo { ... };

typedef struct { ... } Foo;

C ++中'typedef struct'和'struct'之間的一個重要區別是'typedef structs'中的內聯成員初始化不起作用。

// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };

Struct是創建一個數據類型。 typedef是為數據類型設置暱稱。


這篇DDJ文章中 ,Dan Saks解釋了一個小的區域,如果你沒有鍵入你的結構(和類!),那麼錯誤可能會蔓延開來:

如果你願意,你可以想像C ++為每個標籤名稱生成一個typedef,比如

typedef class string string;

不幸的是,這並不完全準確。 我希望這很簡單,但事實並非如此。 C ++不能為結構體,聯合體或枚舉生成這樣的typedef,而不會引入與C的不兼容性。

例如,假設一個C程序聲明了一個名為status的函數和一個結構體:

int status(); struct status;

再次,這可能是不好的做法,但它是C.在這個程序中,狀態(本身)是指功能; 結構狀態指的是類型。

如果C ++自動為標記生成了typedef,那麼當你將這個程序編譯為C ++時,編譯器會生成:

typedef struct status status;

不幸的是,這個類型名稱與函數名稱衝突,程序不能編譯。 這就是為什麼C ++不能簡單地為每個標籤生成一個typedef。

在C ++中,標記的作用與typedef名稱相似,只不過程序可以聲明與標記名稱相同且範圍相同的對象,函數或枚舉器。 在這種情況下,對象,函數或枚舉器名稱將隱藏標記名稱。 該程序只能通過在標籤名稱前使用關鍵字class,struct,union或enum(如適用)來引用標籤名稱。 由這些關鍵字後跟一個標籤組成的類型名稱是一個詳細說明類型說明符。 例如,struct status和enum month是詳細說明類型說明符。

因此,一個包含以下兩者的C程序:

int status(); struct status;

在編譯為C ++時表現相同。 單獨的名稱狀態是指該功能。 程序只能通過使用elaborated-type-specifier結構狀態來引用該類型。

那麼這是如何讓錯誤進入程序的呢? 考慮清單1中的程序。 該程序定義了一個具有默認構造函數的foo類和一個將foo對象轉換為char const *的轉換運算符。 表達方式

p = foo();

主要應構造一個foo對象並應用轉換運算符。 隨後的輸出語句

cout << p << '\n';

應該顯示類foo,但它不會。 它顯示函數foo。

出現這個令人驚訝的結果是因為該程序包含清單2中所示的頭文件lib.h。 這個頭文件定義了一個名為foo的函數。 函數名稱foo隱藏了類名foo,因此在main中對foo的引用是指函數,而不是類。 main可以僅通過使用詳細類型說明符來引用該類,如在

p = class foo();

在整個程序中避免這種混淆的方法是為類名foo添加以下typedef:

typedef class foo foo;

緊接在類定義之前或之後。 該typedef導致類型名稱foo和函數名稱foo(來自庫)之間的衝突,這會觸發編譯時錯誤。

我知道沒有人真的寫這些typedefs是理所當然的。 它需要很多紀律。 由於清單1中錯誤的發生率可能很小,所以很多情況下都不會出現這種問題。 但是,如果軟件中的錯誤可能會導致人身傷害,那麼無論出現錯誤的可能性如何,您都應該寫入typedef。

我無法想像為什麼有人想要在類的範圍內隱藏一個具有函數或對象名稱的類名。 C中的隱藏規則是一個錯誤,它們不應該擴展到C ++中的類。 事實上,你可以糾正錯誤,但它需要額外的編程紀律和努力,而這不需要。


在C ++中沒有區別,但我相信在C中它可以讓你在沒有明確執行的情況下聲明結構Foo的實例:

struct Foo bar;

您不能使用typedef結構的前向聲明。

結構本身是一個匿名類型,所以你沒有一個實際的名字來轉發declare。

typedef struct{
    int one;
    int two;
}myStruct;

像這樣的前向聲明不會奏效:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

有一個區別,但微妙。 以這種方式來看待它: struct Foo引入了一種新類型。 第二個為未命名的struct類型創建一個名為Foo的別名(而不是新類型)。

7.1.3 typedef說明符

1 [...]

使用typedef說明符聲明的名稱將成為typedef名稱。 在其聲明的範圍內,typedef-name在語法上等同於關鍵字,並按照第8章所述的方式命名與標識符關聯的類型。typedef-name因此是另一種類型的同義詞。 typedef-name 不像類聲明(9.1)或枚舉聲明那樣引入新類型

8如果typedef聲明定義了一個未命名的類(或枚舉),那麼聲明聲明的第一個typedef-name是類類型(或枚舉類型),僅用於表示類類型(或枚舉類型) 3.5)。 [例如:

typedef struct { } *ps, S; // S is the class name for linkage purposes

因此,typedef 總是用作另一種類型的佔位符/同義詞。





typedef