簡體   English   中英

C++ 中的“struct”和“typedef struct”之間的區別?

[英]Difference between 'struct' and 'typedef struct' in C++?

C++中,有什么區別:

struct Foo { ... };

和:

typedef struct { ... } Foo;

在 C++ 中,只有細微的差別。 它是 C 的保留,它有所作為。

C 語言標准( C89 §3.1.2.3C99 §6.2.3C11 §6.2.3 )要求為不同類別的標識符使用單獨的命名空間,包括標簽標識符(對於struct / union / enum )和普通標識符(對於typedef和其他標識符)。

如果你只是說:

struct Foo { ... };
Foo x;

你會得到一個編譯器錯誤,因為Foo只在標簽命名空間中定義。

您必須將其聲明為:

struct Foo x;

任何時候你想引用一個Foo ,你總是不得不稱它為struct Foo 這很快就會很煩人,所以你可以添加一個typedef

struct Foo { ... };
typedef struct Foo Foo;

現在struct Foo (在標簽命名空間中)和普通的Foo (在普通標識符命名空間中)都指的是同一個東西,你可以在沒有struct關鍵字的情況下自由聲明Foo類型的對象。


構造:

typedef struct Foo { ... } Foo;

只是聲明和typedef的縮寫。


最后,

typedef struct { ... } Foo;

聲明一個匿名結構並為其創建一個typedef 因此,使用此構造,它在標記命名空間中沒有名稱,只有 typedef 命名空間中的名稱。 這意味着它也不能被前向聲明。 如果要進行前向聲明,則必須在標簽命名空間中為其命名


在 C++ 中,所有struct / union / enum / class聲明的行為就像它們是隱式typedef 'ed,只要名稱沒有被另一個具有相同名稱的聲明隱藏。 有關詳細信息,請參閱Michael Burr 的答案

這篇 DDJ 文章中,Dan Saks 解釋了一個小區域,如果您不對結構(和類:)進行類型定義,錯誤可能會蔓延:

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

typedef class string string;

不幸的是,這並不完全准確。 我希望它是那么簡單,但事實並非如此。 C++ 無法為結構、聯合或枚舉生成此類 typedef,而不會引入與 C 的不兼容性。

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

 int status(); struct status;

同樣,這可能是不好的做法,但它是 C。 在這個程序中,狀態(單獨)是指 function; 結構狀態是指類型。

如果 C++ 確實為標簽自動生成 typedef,那么當您將此程序編譯為 C++ 時,編譯器將生成:

 typedef struct status status;

不幸的是,這個類型名稱會與 function 名稱沖突,程序無法編譯。 這就是為什么 C++ 不能簡單地為每個標簽生成一個 typedef。

In C++, tags act just like typedef names, except that a program can declare an object, function, or enumerator with the same name and the same scope as a tag. 在這種情況下,object、function 或枚舉器名稱會隱藏標簽名稱。 程序只能通過在標簽名稱前使用關鍵字 class、struct、union 或 enum(視情況而定)來引用標簽名稱。 由這些關鍵字之一和標簽組成的類型名稱是詳細類型說明符。 例如,struct status 和 enum month 是詳細的類型說明符。

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

 int status(); struct status;

編譯為 C++ 時的行為相同。 僅名稱狀態是指 function。 程序只能通過使用詳細類型說明符結構狀態來引用類型。

那么這如何讓錯誤潛入程序中呢? 考慮清單 1中的程序。 該程序使用默認構造函數定義了 class foo,以及將 foo object 轉換為 char const * 的轉換運算符。 表達方式

p = foo();

在 main 中應該構造一個 foo object 並應用轉換運算符。 隨后的 output 語句

cout << p << '\n';

應該顯示 class foo,但它沒有。 它顯示 function foo。

之所以會出現這個令人驚訝的結果,是因為該程序包含清單 2中所示的 header lib.h。 這個 header 定義了一個 function 也叫 foo。 The function name foo hides the class name foo, so the reference to foo in main refers to the function, not the class. main 只能通過使用詳細類型說明符來引用 class,如

p = class foo();

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

 typedef class foo foo;

在 class 定義之前或之后。 此 typedef 導致類型名稱 foo 和 function 名稱 foo (來自庫)之間的沖突,這將觸發編譯時錯誤。

我知道沒有人會理所當然地實際編寫這些 typedef。 它需要大量的紀律。 由於諸如清單 1中的錯誤的發生率可能非常小,因此很多人都不會遇到這個問題。 但是,如果您的軟件中的錯誤可能會導致人身傷害,那么無論錯誤多么不可能,您都應該編寫 typedef。

I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. C 中的隱藏規則是錯誤的,它們不應該擴展到 C++ 中的類。 確實,您可以糾正錯誤,但它需要額外的編程紀律和不必要的努力。

還有一個重要的區別: typedef不能被前向聲明。 因此,對於typedef選項,您必須#include包含typedef的文件,這意味着#include s 您的.h的所有內容也包括該文件,無論它是否直接需要它,等等。 它肯定會影響您在大型項目上的構建時間。

如果沒有typedef ,在某些情況下,您只需添加struct Foo; .h文件的頂部,並且僅在.cpp文件中#include結構定義。

區別,但很微妙。 這樣看: struct Foo引入了一種新類型。 第二個為未命名的struct類型創建一個名為 Foo 的別名(而不是新類型)。

7.1.3 typedef 說明符

1 [...]

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

8 如果 typedef 聲明定義了一個未命名的 class(或 enum),則該聲明聲明的第一個 typedef-name 為 class 類型(或 enum 類型)用於表示 ZA2F2ED4F8EBC2CBB4C21A21umDZ 類型(僅用於鏈接類型)(AB 3.5)。 [ 例子:

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

因此,typedef始終用作另一種類型的占位符/同義詞。

您不能將前向聲明與 typedef 結構一起使用。

結構本身是一種匿名類型,因此您沒有要轉發聲明的實際名稱。

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

像這樣的前向聲明不起作用:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

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

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; };

C++ 沒有區別,但我相信 C 將允許您聲明 struct Foo 的實例而無需明確執行:

struct Foo bar;

struct 是創建一個數據類型。 typedef 是為一個數據類型設置一個昵稱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM