前向宣告
範例:
class B; // 前向宣告 class A { public: void f(B b); }; class B { public: void g(A a); };
前向宣告
- 類別應該先宣告,後使用。
- 如果需要在某個類別的宣告之前引用該類別,則應進行前向宣告。
- 前向宣告只為程式引入一個識別符,但具體的定義在其他地方。
- 範例:
class Fred; // 前向宣告 class Barney { Fred x; // 錯誤:類別 Fred 的宣告尚未完善 }; class Fred { Barney y; };
前向宣告的注意事項
使用前向宣告雖然可以解決一些問題,但它並非萬能的。
- 在提供一個完整的類別宣告之前,不能宣告該類別的物件,也不能在內聯成員函數中使用該類別的物件。
- 當使用前向宣告時,只能使用被宣告的符號,而不能涉及類別的任何細節。
結構體
- 結構體是一種特殊形式的類別。與類別的唯一差異是:類別的預設存取權限是
private
,而結構體的預設存取權限是public
。 - 結構體存在的主要原因是為了與 C 語言保持兼容。
什麼時候用結構體而不用類別
- 當定義的主要目的是保存資料,而不包含太多操作時,通常會使用結構體。
- 人們習慣將結構體的資料成員設為
public
,因此在這種情況下使用結構體更為方便。
結構體的定義
struct 結構體名稱 { 公有成員 protected: 受保護的成員 private: 私有成員 };
結構體的初始化
- 如果一個結構體的所有資料成員都是公有成員,且沒有使用者自訂的建構子,也沒有基類和虛擬函數(基類和虛擬函數將在後續章節中介紹),那麼這個結構體的變數可以用以下語法形式進行初始化:
型別名 變數名 = { 成員資料1初始值, 成員資料2初始值, …… };
例 4-7 用結構體表示學生的基本資訊
#include <iostream> #include <iomanip> #include <string> using namespace std; struct Student { // 學生資訊結構體 int num; // 學號 string name; // 姓名,字串物件,將在第6章詳細介紹 char sex; // 性別 int age; // 年齡 }; int main() { Student stu = { 97001, "Lin Lin", 'F', 19 }; cout << "Num: " << stu.num << endl; cout << "Name: " << stu.name << endl; cout << "Sex: " << stu.sex << endl; cout << "Age: " << stu.age << endl; return 0; } 執行結果: Num: 97001 Name: Lin Lin Sex: F Age: 19
聯合體
- 聯合體(union)是一種特殊的資料結構,允許不同類型的資料共用同一段記憶體。宣告形式如下:
union 聯合體名稱 { 公有成員 protected: 受保護的成員 private: 私有成員 };
聯合體的特點
- 聯合體的所有成員共用同一組記憶體單元,這意味著任何兩個成員不能同時有效。當一個成員被賦值時,其他成員的值可能會改變。
聯合體的內存分配
union Mark { // 表示成績的聯合體 char grade; // 等級制的成績 bool pass; // 只記是否通過課程的成績 int percent; // 百分制的成績 };
無名聯合
- 無名聯合是一種不帶標識符的聯合體,可以直接在程式中使用它的成員。範例如下:
union { int i; float f; }; int main() { i = 10; f = 2.2; // 無名聯合沒有標識符,可以直接使用成員名稱
例 4-8 使用聯合體保存成績資訊並輸出
#include <string> #include <iostream> using namespace std; class ExamInfo { private: string name; // 課程名稱 enum { GRADE, PASS, PERCENTAGE } mode; // 計分方式 union { char grade; // 等級制的成績 bool pass; // 只記是否通過課程的成績 int percent; // 百分制的成績 }; public: // 三種建構子,分別用等級、是否通過和百分數初始化 ExamInfo(string name, char grade) : name(name), mode(GRADE), grade(grade) { } ExamInfo(string name, bool pass) : name(name), mode(PASS), pass(pass) { } ExamInfo(string name, int percent) : name(name), mode(PERCENTAGE), percent(percent) { } void show(); }; void ExamInfo::show() { cout << name << ": "; switch (mode) { case GRADE: cout << grade; break; case PASS: cout << (pass ? "PASS" : "FAIL"); break; case PERCENTAGE: cout << percent; break; } cout << endl; } int main() { ExamInfo course1("English", 'B'); ExamInfo course2("Calculus", true); ExamInfo course3("C++ Programming", 85); course1.show(); course2.show(); course3.show(); return 0; } 執行結果: English: B Calculus: PASS C++ Programming: 85