C++ 型別系統 (現代的 C++)
型別的 概念是非常重要的在 C++。每個變數、函式引數和函式傳回值必須有型別才能編譯。此外, (包括常值) 編譯器隱含運算式給每一個型別,然後再評估之前。型別的範例包括 int 儲存整數值, double 存放浮點值 (也稱為 純量 資料型別),或標準程式庫類別 std::basic_string 儲存文字。您可以藉由定義 class 或 struct建立自己的型別。這個型別指定為變數的記憶體數量 (或運算式結果) 將被配置,這種值在該變數,這些值 (位元組合) 轉譯方式和作業可能會儲存可執行至這個。本文包含 C++ 型別系統的主要功能非正式的概觀。
用語
變數:資料數目的符號名稱,使名稱可以用來存取資料將在定義程式碼的範圍中。在 C++ 中, 「變更為」通常用來參考純量資料型別執行個體,,而其他型別的執行個體通常稱為「Object」。
物件:為了簡化和一致性,本文使用這個詞彙「物件是指類別或結構的所有執行個體,並在通用而言時使用它包含的所有型別,即使純量變數。
POD 型別 (一般舊資料):資料型別 C++ 這非正式的分類參考是純量型別 (如基本型別) 或部分是 POD 類別。POD 類別不是也不是 PODS 的靜態資料成員,而不是使用者定義的建構函式、使用者定義解構函式或使用者定義的指派運算子。此外, POD 類別具有虛擬函式、沒有基底類別且私用或受保護的非靜態資料成員。POD 型別為外部資料交換常用的,例如在只有 POD 型別) 的 C 語言撰寫的模組 (。
指定變數和函式型別
C++ 是一種 強型別 語言,並且也 靜態型別;每個物件都有一個型別,且該型別永遠不會變更 (以資料物件混淆)。
當您宣告變數 在您的程式碼,則必須明確指定其型別,或使用 auto 關鍵字會指示編譯器從初始設定式推算型別。
如果值不為函式,傳回當您宣告函式 在程式碼中,您必須指定每個引數和其傳回值的型別為 void 。例外狀況是您使用函式樣板,允許任意型別的引數。
在您先宣告變數後,就不能變更其型別在一些最新的。不過,您可以複製變數值或函式的傳回值為不同類型的另一個變數。這類作業稱為型別轉換,有時候是必要的,但是也是資料遺失或無效的潛在來源。
當您宣告 POD 型別的變數時,強烈建議您將它初始化,表示為其初始值。除非您使用變數,它會包含「記憶體和任何位元先前意外該記憶體位置。特別是如果您來自另一種語言而定,可處理初始化這是要記住的 C++ 的一個重要層面。當宣告非 POD 類別型別的變數時,建構函式處理初始化。
下列範例顯示具有某些描述的一些簡單變數宣告每個的。這個範例也會顯示編譯器如何使用型別資訊允許或不允許在變數的某些後續作業。
int result = 0; // Declare and initialize an integer.
double coefficient = 10.8; // Declare and initialize a floating
// point value.
auto name = "Lady G."; // Declare a variable and let compiler
// deduce the type.
auto address; // error. Compiler cannot deduce a type
// without an intializing value.
age = 12; // error. Variable declaration must
// specify a type or use auto!
result = "Kenny G."; // error. Can’t assign text to an int.
string result = "zero"; // error. Can’t redefine a variable with
// new type.
int maxValue; // Not recommended! maxValue contains
// garbage bits until it is initialized.
基本 (固定) 型別
不同於某些程式語言而言, C++ 沒有其他型別衍生的通用基底型別。此語言的 Visual C++ 實作包含許多 基本型別,也就是 內建型別。這包括數字型別 ( int, double, long, bool,加上 ASCII 和 UNICODE 字元的 char 和 wchar_t 型別,分別。大部分基本型別 (除了 bool、 double、 wchar_t 和相關型別) 都未簽署的版本,修改值的範圍變數可以儲存。例如, int,儲存 32 位元帶正負號的整數,可表示從 -2,147,483,648 到 2,147,483,647 的值。unsigned int,它會儲存為 32 位元,可以儲存從 0 到 4,294,967,295 的值。可能的值總數在每個案例的相同;只有這個範圍是不同的。
基本型別是由編譯器辨識,具有固定規則控制哪些作業在它們可執行,,以及如何轉換成其他基本型別 (Primitive Type)。如需內建型別及其大小和數值限制的完整清單,請參閱 主要資料型別 (C++)。
下圖顯示內建型別的相對大小:
下表列出常用的基本型別:
型別 |
Size |
註解 |
---|---|---|
int |
4 個位元組 |
整數值的預設選項。 |
double |
8 個位元組 |
浮點值的預設選項。 |
bool |
1 個位元組 |
表示可以是 true 或 false 的值。 |
char |
1 個位元組 |
為 ASCII 字元使用在永遠不會必須轉換成 UNICODE 的較舊的 C-Style 字串或 std::string 的物件。 |
wchar_t |
2 個位元組 |
表示「在 UNICODE 格式會輸入的寬字元」的值 (其為 UTF-16,其他作業系統可能會不同)。這是用於型別 std::wstring字串的字元型別。 |
unsigned char |
1 個位元組 |
C++ 沒有內建的 byte 型別。使用不帶正負號的字元表示位元組值。 |
unsigned int |
4 個位元組 |
預設位元旗標選項。 |
long long |
8 個位元組 |
表示極大的整數值。 |
void 型別
void 型別屬於特定型別;您不能宣告型別 void的變數,不過,您可以宣告型別 ( void * 之 void的指標) 變數,有時候是必要的,當配置未經處理 (不具型別) 記憶體。然而,對 void 的指標不是型別安全,而且會在現代 C++ 強烈通常會鼓勵。在函式宣告, void 傳回值表示函式未傳回值;這是 void的共用和接受用途。當 C 語言需要有宣告零參數在參數清單的 void ,例如, fou(void)的函式時,這種作法在現代 C++ 中不建議使用,而且應該宣告為 fou()。如需詳細資訊,請參閱型別轉換和型別安全 (現代的 C++)。
常數型別限定詞
任何內建或使用者定義型別可以由常數關鍵字限定。此外,成員函式可能是-即使限定和 const-多載的 const。const 型別的值,在初始化之後,就無法修改。
const double PI = 3.1415;
PI = .75 //Error. Cannot modify const variable.
const 限定詞在函式廣泛使用,而變數宣告和「常數正確性」是在 C++ 中的一個重要概念;基本上表示使用 const ,確保在編譯時期,沒有不小心修改值。如需詳細資訊,請參閱const (C++)。
const 型別其非 Const 版本不同;例如, const int 是 int的不同型別。當您必須從變數時,取消 常數岬 您可以使用這些不常見的執行個體中的 C++ const_cast 運算子。如需詳細資訊,請參閱型別轉換和型別安全 (現代的 C++)。
資料型別
嚴格來說, C++ 語言沒有內建的 string 型別; char 和 wchar_t 存放單一字元–您必須宣告這些型別存取字串,將結尾的 NULL 值 (例如, ASCII ‘\0’) 傳遞到最後一個有效字元的陣列元素中 (也稱為 C-Style 字串")。C-Style 字串需要更多程式碼撰寫或使用外部資料公用程式程式庫函式。但是,在現代 C++,我們有標準程式庫型別 std::string (8 位元 char型別的字串) 或 std::wstring (16 位元 wchar_t型別的字串)。這些 STL 容器可以有值,原生字串型別,因為它們是在所有標準 C++ 建置環境包括標準程式庫的一部分。請使用 #include <string> 指示詞讓這些型別可在您的程式。(如果您正在使用 MFC 或 ATL, CString 類別也是可用的,但是,做為 C++ 標準的一部分)。使用 null 結尾字元陣列 (先前提到的 C-Style 字串) 在現代 C++ 強烈建議您不要。如需如何決定哪一個詳細資訊字串型別用於現代 C++ 程式以及如何將各種型別之間的詳細資訊,請參閱 字串和文字 (現代的 C++)。
使用者定義型別
當您定義 class、 struct、 union或 enum,建構用於其餘的程式碼,就如同基本型別。它有已知的大小在記憶體和如何的規則可以用來套用至其編譯時期檢查的,因此,在執行階段,在程式的存留期。內建基本型別和使用者定義型別之間的主要差異如下:
編譯器沒有使用者定義型別的內建知識。包含在編譯處理程序期間時,第一次遇到這個定義會得知」型別。
您指定哪項作業在型別上執行,因此,它如何轉換為其他型別,藉由定義 (透過多載) 適當的運算子,無論是在類別成員或非成員函式。如需詳細資訊,請參閱多載化。
它們不需要靜態型別 (目標型別從未變更的規則。透過繼承和 多型機制,做為類別的使用者定義型別宣告的變數 (稱為類別的物件執行個體) 可能會有不同的型別在執行階段會在編譯時期。如需詳細資訊,請參閱在衍生的類別。
指標型別
使用特殊宣告子 * (星號),追溯到 C 語言的先前版本中, C++ 繼續讓您宣告指標型別的變數。指標型別在儲存實際資料值的記憶體存放位置的位址。在現代 C++,這些指 原始指標和存取程式碼進行特定運算子 * (星號) 或 -> (虛線與大於)。這個呼叫 的參考,以及哪個您使用的是取決於您是否要參考純量的指標或參考成員的指標物件的。以和指標型別使用長度為其中一個程序開發的 C 和 C++ 的最具挑戰性和最 Scrum 方面。本節說明一些事實和做法有助於使用原始指標,如果您要對,不過,在現代 C++ 不再需要 (建議使用) 為物件擁有權使用原始指標,因為 智慧型指標 的演進 (討論更多區段結尾)。為檢視物件使用原始指標是有用的,和安全性,但是,如果您必須為物件擁有權使用它們,您應該這樣做小心和非常仔細考量這些主控物件如何建立和終結。
您應該知道的第一件事宣告原始指標變數將配置要求儲存記憶體位置的位址的記憶體指標,參考當它被解除參考時。記憶體的配置資料值 (也稱為 備份存放區) 不是配置的。換句話說,您可以宣告一原始指標變數,您建立記憶體位址變數,而不是變數實際的資料。請在目前的參考指標變數它在程式中包含有效位址給備份存放區將會產生未定義的行為 (通常是嚴重錯誤)。下列範例示範這種錯誤:
int* pNumber; // Declare a pointer-to-int variable.
*pNumber = 10; // error. Although this may compile, it is
// a serious error. We are dereferencing an
// uninitialized pointer variable with no
// allocated memory to point to.
這個範例取值指標型別沒有儲存任何記憶體的配置實際整數資料或有效的記憶體位址指派給它。下列程式碼來修正這些錯誤:
int number = 10; // Declare and initialize a local integer
// variable for data backing store.
int* pNumber = &number; // Declare and initialize a local integer
// pointer variable to a valid memory
// address to that backing store.
...
*pNumber = 41; // Dereference and store a new value in
// the memory pointed to by
// pNumber, the integer variable called
// “number”. Note “number” was changed, not
// “pNumber”.
建立 pNumber 指向的備份存放區的程式碼範例會使用本機堆疊記憶體。我們為了簡單起見使用基本型別。實際上,指標的備份存放區通常是在記憶體區域的動態配置呼叫 堆積 的使用者定義型別 (或「請釋放存放區) 使用 new 關鍵字 (在 C# 運算式程式設計中,較舊的 malloc() C 執行階段程式庫函式使用)。一旦配置,這些「變數」通常稱為「對」,,特別是如果它們根據類別定義。與 new 配置的記憶體必須由對應的 delete 陳述式 (刪除,或者,如果您使用 malloc() 函式配置時, C 執行階段函式 free())。
不過,忘記刪除一個動態配置物件特別將複雜程式碼很容易,造成資源呼叫 記憶體遺漏的Bug。因此,使用原始指標在現代 C++ 強烈建議您不要。包裝在 智慧型指標的一般指標幾乎永遠是最好的,將會自動釋放記憶體,當其解構函式叫用時 (當程式碼超出智慧型指標範圍);使用智慧型指標實際上您排除錯誤整個類別在您的 C++ 程式。在下列範例中,假設 MyClass 是具有公用方法 DoSomeWork();的使用者定義型別
void someFunction() {
unique_ptr<MyClass> pMc(new MyClass);
pMc->DoSomeWork();
}
// No memory leak. Out-of-scope automatically calls the destructor
// for the unique_ptr, freeing the resource.
如需智慧型指標的詳細資訊,請參閱 智慧型指標 (現代的 C++)。
如需指標轉換的詳細資訊,請參閱 型別轉換和型別安全 (現代的 C++)。
如需目標的詳細資訊請一般而言,請參閱 指標。
視窗資料型別
在 C 和 C++ 的傳統 Win32 程式設計中,大部分的函式使用視窗專屬 typedef 和 #define 巨集 (定義於 windef.h) 指定參數和傳回值的型別。這些視窗的資料型別是主要特殊名稱 (別名) 將 C/C++ 內建型別。如需這些 Typedef 和前置處理器定義的完整清單,請參閱 Windows Data Types。這些 Typedef,例如 HRESULT 和 LCID,有助於和描述。其他,例如 INT,沒有特殊意義是基本 C++ 型別的別名。其他視窗資料型別有從天 C 程式和 16 位元處理器保留的名稱,並沒有目的或意義在現代硬體或作業系統。也有特殊資料型別與 Windows 執行階段執行階段程式庫,列出為 Windows Runtime base data types。在現代 C++,一般方針是慣用 C++ 基本型別,除非視窗類型會傳達值如何進行額外的意思是解譯的。
詳細資訊
如需 C++ 型別系統的詳細資訊,請參閱下列主題。
與問題的描述 值 型別與其用途相關。 |
|
描述一般型別轉換發行並顯示如何避免這些陷阱。 |