C++結構體類型的定義和初始化
有時需要將不同類型的資料群組合成一個有機的整體,以供使用者方便地使用。這些組合在一個整體中的資料是互相聯絡的。例如,一個學生的學號、姓名、性別、年齡、成績、家庭地址等項,都是這個學生的屬性,見圖
可以看到學號(num)、姓名(name)、性別(sex)、年齡(age)、成績(score )、地址(addr)是與姓名為“Li Fun”的學生有關的。如果在程式中將num,name,sex,age,score,addr分別定義為互相獨立的變數,就難以反映出它們之間的內在聯絡。應當把它們組織成一個組合項,在一個組合項中包含若干個類型不同(當然也可以相同)的資料項目。C和C++允許使用者自己指定這樣一種資料類型,它稱為結構體。它相當於其他進階語言中的記錄(record)。
例如,可以通過下面的聲明來建立如圖所示的資料類型。
struct Student//聲明一個結構體類型Student{ int num; //包括一個整型變數num char name[20]; //包括一個字元數組name,可以容納20個字元 char sex; //包括一個字元變數sex int age; //包括一個整型變數age float score; //包括一個單精確度型變數 char addr[30]; //包括一個字元數組addr,可以容納30個字元}; //最後有一個分號
這樣,程式設計者就聲明了一個新的結構體類型Student(struct是聲明結構體類型時所必須使用的關鍵字,不能省略),它向編譯系統聲明: 這是一種結構體類型,它包括num, name, sex, age, score, addr等不同類型的資料項目。應當說明Student是一個類型名,它和系統提供的標準類型(如int、char、float、double 一樣,都可以用來定義變數,只不過結構體類型需要事先由使用者自己聲明而已。
聲明一個結構體類型的一般形式為:
結構體類型名用來作結構體類型的標誌。上面的聲明中Student就是結構體類型名。大括弧內是該結構體中的全部成員(member),由它們組成一個特定的結構體。上例中的num,name,sex,score等都是結構體中的成員。在聲明一個結構體類型時必須對各成員都進行型別宣告即類型名 成員名;每一個成員也稱為結構體中的一個域(field)。成員表列又稱為域表。
聲明結構體類型的位置一般在檔案的開頭,在所有函數(包括main函數)之前,以便本檔案中所有的函數都能利用它來定義變數。當然也可以在函數中聲明結構體類型。
在C語言中,結構體的成員只能是資料(如上面例子中所表示的那樣)。C++對此加以擴充,結構體的成員既可以包括資料(即資料成員),又可以包括函數(即函數成員),以適應物件導向的程式設計。
但是由於C++提供了類(class )類型,一般情況下,不必使用帶函數的結構體,因此在本章中只介紹只含資料成員的結構體,有關包含函數成員的結構體將在後續章節進行介紹。
結構體類型變數的定義方法及其初始化
以上只是指定了一種結構體類型,它相當於一個模型,但其中並無具體資料,系統也不為之分配實際的記憶體單元為了能在程式中使用結構體類型的資料,應當定義結構體類型的變數,並在其中存放具體的資料。
定義結構體類型變數的方法可以採取以下3種方法定義結構體類型的變數。
1) 先聲明結構體類型再定義變數名
如上面已定義了一個結構體類型Student,可以用它來定義結構體變數。如:
在C語言中,在定義結構體變數時,要在結構體類型名前面加上關鍵字Sttuct,C++ 保留了C的用法,如:
struct Student studentl, student2;
提倡讀者在編寫C++程式時,使用C++新提出來的方法,即不必在定義結構體變數時加關鍵字Struct,這樣使用更方便,而且與第8章中介紹的用類(class)名定義類對象的用法一致。
以上定義了student1和student2為結構體類型Student的變數,即它們具有Student類型的結構。如圖所示。
在定義了結構體變數後,系統會為之分配記憶體單元。例如student1和student2在記憶體中各佔63個位元組(4+20+1+4+4+30=63)。
2) 在宣告類型的同時定義變數。例如:
struct Student //聲明結構體類型Student{ int num; char name[20]; char sex; int age; float score; char addr[30];}student1, student2; //定義兩個結構體類型Student的變數student1,student2
這種形式的定義的一般形式為:
3) 直接定義結構體類型變數。其一般形式為:
struct //注意沒有結構體類型名{ 成員表列}變數名表列;
這種方法雖然合法,但很少使用。提倡先定義類型後定義變數的第(1)種方法。在程式比較簡單,結構體類型只在本檔案中使用的情況下,也可以用第(2)種方法。
關於結構體類型,有幾點要說明:
1) 不要誤認為凡是結構體類型都有相同的結構。實際上,每一種結構體類型都有自己的結構,可以定義出許多種具體的結構體類型。
2) 類型與變數是不同的概念,不要混淆。只能對結構體變數中的成員賦值,而不能對結構體類型賦值。在編譯時間,是不會為類型分配空間的,只為變數分配空間。
3) 對結構體中的成員(即“域”),可以單獨使用,它的作用與地位相當於普通變數。
4) 成員也可以是一個結構體變數。如:
struct Date //聲明一個結構體類型Date{ int month; int day; int year;};struct Student //聲明一個結構體類型Student{ int num; char name[20]; char sex; int age; Date birthday; char addr[30];}student1, student2; //定義student1和student2為結構體類型Student的變數
首先聲明一個Date類型,它代表“日期”,包括3個成員:rnomh(月)、day (日)、year(年)。然後在聲明Studcm類型時,將成員birthday指定為Date類型。Student的結構見圖所示。已聲明的類型Date與其他類型(如im,char)—樣,也可以用來定義成員的類型。
5) 結構體中的成員名可以與程式中的變數名相同,但二者沒有關係。例如,程式中可以另定義一個整型變數num,它與student中的num是兩回事,互不影響。
結構體變數的初始化
和其他類型變數一樣,對結構體變數可以在定義時指定初始值。如:
struct Student{ int num; char name[20]; char sex; int age; float score; char addr[30];}student1={10001, "Zhang Xin", 'M', 19, 90.5, "Shanghai"};
這樣,變數student1中的資料如圖中所示。
也可以採取宣告類型與定義變數分開的形式,在定義變數時進行初始化:
Student student2 = { 10002, "Wang Li", "F", 20, 98, "Beijing"}; //Student是已聲明的結構體類型
C++結構體變數的引用
在定義了結構體變數以後,當然可以引用這個變數,常用的方法有以下幾種。
1) 可以將一個結構體變數的值賦給另一個具有相同結構的結構體變數。
如上面的student1和student2都是student類型的變數,可以這樣賦值:
2) 可以引用一個結構體變數中的一個成員的值。
例如, student1.num表示結構體變數student1中的成員的值,如果student1的值如圖所示,則student1.num的值為10001。
引用結構體變數中成員的一般方式為:
例如可以這樣對變數的成員賦值:
3) 如果成員本身也是一個結構體類型,則要用若干個成員運算子,一級一級地找到最低一級的成員。
例如,對上面定義的結構體變數student1,可以這樣訪問各成員:
student1.num (引用結構體變數student1中的num成員)
如果想引用student1變數中的birthday成員中的month成員,不能寫成student1.month,必須逐級引用,即
student1.birthday.month=12; (引用結構體變數student1中的birthday成員中的month成員)
4) 不能將一個結構體變數作為一個整體進行輸入和輸出。
例如,已定義student1和student2為結構體變數,並且它們已有值。不能企圖這樣輸出結構體變數中的各成員的值
只能對結構體變數中的各個成員分別進行輸入和輸出。
5) 對結構體變數的成員可以像普通變數一樣進行各種運算(根據其類型決定可以進行的運算種類)。例如:
student2.score=student1.score; sum=student1.score+student2.score; student1.age++; ++student1.age;
由於“.”運算子的優先順序最高,student1.age++相當於(student1.age)++ 。++是對student1.age進行自加運算,而不是先對age進行自加運算。
6) 可以引用結構體變數成員的地址,也可以引用結構體變數的地址。如:
cout<<&student1; //輸出student1的首地址 cout<<&student1.age; //輸出student1.age的地址
結構體變數的地址主要用作函數參數,將結構體變數的地址傳遞給形參。
【例】引用結構體變數中的成員。
#include <iostream>using namespace std;struct Date//聲明結構體類型Date{ int month; int day; int year;};struct Student//聲明結構體類型Student{ int num; char name[20]; char sex; Date birthday; //聲明birthday為Date類型的成員 float score;}student1,student2={10002,"Wang Li",'f',5,23,1982,89.5};//定義Student 類型的變數student1,student2,並對student2初始化int main( ){ student1=student2; //將student2各成員的值賦予student1的相應成員 cout<<student1.num<<endl; //輸出student1中的num成員的值 cout<<student1.name<<endl; //輸出student1中的name成員的值 cout<<student1.sex<<endl; //輸出student1中的sex成員的值 cout<<student1.birthday.month<<'/'<<student1.birthday.day<<'/' <<student1.birthday.year<<endl; //輸出student1中的birthday各成員的值 cout<<student1.score<<endl; return 0;}
運行結果如下:
10002Wang Lif5/23/198289.5