日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

C++結(jié)構(gòu)體完全攻略

 柳鳴蟬 2019-11-03
結(jié)構(gòu)體是一個(gè)由程序員定義的數(shù)據(jù)類型,可以容納許多不同的數(shù)據(jù)值。在過去,面向?qū)ο缶幊痰膽?yīng)用尚未普及之前,程序員通常使用這些從邏輯上連接在一起的數(shù)據(jù)組合到一個(gè)單元中。一旦結(jié)構(gòu)體類型被聲明并且其數(shù)據(jù)成員被標(biāo)識(shí),即可創(chuàng)建該類型的多個(gè)變量,就像可以為同一個(gè)類創(chuàng)建多個(gè)對(duì)象一樣。

雖然今天結(jié)構(gòu)體較少使用,但知道它們是什么,以及如何使用它們?nèi)匀缓苤匾@并不僅僅是因?yàn)榭梢栽谳^老的程序中遇到它們,還因?yàn)樵谀承┣闆r下,類的實(shí)例無法使用,這時(shí)必須使用結(jié)構(gòu)體。

聲明結(jié)構(gòu)體的方式和聲明類的方式大致相同,其區(qū)別如下:
  • 使用關(guān)鍵字 struct 而不是關(guān)鍵字 class。
  • 盡管結(jié)構(gòu)體可以包含成員函數(shù),但它們很少這樣做。所以,通常情況下結(jié)構(gòu)體聲明只會(huì)聲明成員變量。
  • 結(jié)構(gòu)體聲明通常不包括 public 或 private 的訪問修飾符。
  • 類成員默認(rèn)情況是私有的,而結(jié)構(gòu)體的成員則默認(rèn)為 public。程序員通常希望它們保持公開,只需使用默認(rèn)值即可。

以下是一個(gè)結(jié)構(gòu)體聲明的示例,該結(jié)構(gòu)體將 5 個(gè)變量綁定在一起,保存了員工的工資單數(shù)據(jù)。這個(gè)特殊結(jié)構(gòu)體的名稱是 PayRoll。請(qǐng)注意,它以大寫字母開頭,這和類名使用大寫字母開頭的約定一樣。另外還要注意,與類聲明一樣,在結(jié)構(gòu)體聲明的大括號(hào)后面必須有一個(gè)分號(hào)。
  1. struct PayRoll
  2. {
  3. int empNumber;
  4. string name;
  5. double hours,payRate,grossPay;
  6. };
正如在類的對(duì)象被創(chuàng)建之前,類聲明不會(huì)被實(shí)例化一樣,結(jié)構(gòu)體聲明不會(huì)創(chuàng)建任何結(jié)構(gòu)體的實(shí)例。本示例中的結(jié)構(gòu)體聲明只是告訴編譯器PayRoll結(jié)構(gòu)體看起來的樣子。它本質(zhì)上是創(chuàng)建一個(gè)名為 PayRoll 的新數(shù)據(jù)類型。

定義 PayRoll 結(jié)構(gòu)體的變量和定義其他任何變量的方式并無二致,首先列出數(shù)據(jù)類型,然后是變量名稱。以下定義語句創(chuàng)建了 PayRoll 結(jié)構(gòu)體的 3 個(gè)變量:

PayRoll deptHead, foreman, associate;

它們每一個(gè)都是 PayRoll 結(jié)構(gòu)體的實(shí)例,可以被分配和擁有自己的內(nèi)存,以保存其成員數(shù)據(jù)。請(qǐng)注意,盡管 3 個(gè)結(jié)構(gòu)體變量具有不同的名稱,但每個(gè)變量都包含具有相同名稱的成員,如圖 1 所示。

每個(gè)結(jié)構(gòu)體變量都包含具有相同名稱的成員
圖 1 每個(gè)結(jié)構(gòu)體變量都包含具有相同名稱的成員

初始化結(jié)構(gòu)體

當(dāng)定義結(jié)構(gòu)體變量時(shí),可以通過兩種方式初始化它:使用初始化列表或構(gòu)造函數(shù)。

初始化列表

初始化結(jié)構(gòu)體變量成員的最簡單的方法是使用初始化列表。初始化列表是用于初始化一組內(nèi)存位置的值列表。列表中的項(xiàng)目用逗號(hào)分隔并用大括號(hào)括起來。

例如,假設(shè)已經(jīng)聲明了以下 Date 結(jié)構(gòu)體:
  1. struct Date
  2. {
  3. int day, month, year;
  4. };
定義和初始化 Date 變量的方式是:先指定變量名,后接賦值運(yùn)算符和初始化列表,如下所示:

Date birthday = {23, 8, 1983};

該聲明定義 birthday 是一個(gè) Date 結(jié)構(gòu)體的變量,大括號(hào)內(nèi)的值按順序分配給其成員。所以 birthday 的數(shù)據(jù)成員已初始化,如圖 2 所示。

已經(jīng)初始化的 birthday 的數(shù)據(jù)成員
圖 2 已經(jīng)初始化的 birthday 的數(shù)據(jù)成員

也可以僅初始化結(jié)構(gòu)體變量的部分成員。例如,如果僅知道要存儲(chǔ)的生日是8月23日, 但不知道年份,則可以按以下方式定義和初始化變量:

Date birthday = {23,8};

這里只有 day 和 month 成員被初始化,year 成員未初始化。但是,如果某個(gè)結(jié)構(gòu)成員未被初始化,則所有跟在它后面的成員都需要保留為未初始化。使用初始化列表時(shí),C++ 不提供跳過成員的方法。以下語句試圖跳過 month 成員的初始化。這是不合法的。

Date birthday = {23,1983}; //非法

還有一點(diǎn)很重要,不能在結(jié)構(gòu)體聲明中初始化結(jié)構(gòu)體成員,因?yàn)榻Y(jié)構(gòu)體聲明只是創(chuàng)建一個(gè)新的數(shù)據(jù)類型,還不存在這種類型的變量。例如,以下聲明是非法的:
  1. //非法結(jié)構(gòu)體聲明
  2. struct Date
  3. {
  4. int day = 23,
  5. month = 8,
  6. year = 1983;
  7. };
因?yàn)榻Y(jié)構(gòu)體聲明只聲明一個(gè)結(jié)構(gòu)體“看起來是什么樣子的”,所以不會(huì)在內(nèi)存中創(chuàng)建成員變量。只有通過定義該結(jié)構(gòu)體類型的變量來實(shí)例化結(jié)構(gòu)體,才有地方存儲(chǔ)初始值。

構(gòu)造函數(shù)初始化結(jié)構(gòu)體

雖然初始化列表易于使用,但它有兩個(gè)缺點(diǎn):
  1. 如果有某個(gè)成員未被初始化,那么在這種情況下,跟隨在該成員后面的成員都不能初始化。
  2. 如果結(jié)構(gòu)體包括任何諸如字符串之類的對(duì)象,那么在許多編譯器上它都將無法運(yùn)行。

在這些情況下,可以使用構(gòu)造函數(shù)來初始化結(jié)構(gòu)體成員變量,這和初始化類成員變量是相同的。與類構(gòu)造函數(shù)一樣,結(jié)構(gòu)體的構(gòu)造函數(shù)必須是與結(jié)構(gòu)體名稱相同的公共成員函數(shù),并且沒有返回類型。因?yàn)槟J(rèn)情況下,所有結(jié)構(gòu)體成員都是公開的,所以不需要使用關(guān)鍵字 public。

以下是一個(gè)名為 Employee 的結(jié)構(gòu)體的聲明語句,它包含一個(gè)具有兩參數(shù)的構(gòu)造函數(shù),以便在創(chuàng)建一個(gè) Employee 變量而不向其傳遞任何參數(shù)時(shí),提供默認(rèn)值:
  1. struct Employee
  2. {
  3. string name; // 員工姓名
  4. int vacationDays, // 允許的年假
  5. daysUsed; //已使用的年假天數(shù)
  6. Employee (string n ="",int d = 0) // 構(gòu)造函數(shù)
  7. {
  8. name = n;
  9. vacationDays = 10;
  10. daysUsed = d;
  11. }
  12. };

訪問結(jié)構(gòu)體成員

結(jié)構(gòu)體成員的訪問方式與類的公共成員一樣,都是使用點(diǎn)運(yùn)算符。但是,類的數(shù)據(jù)成員通常是私有的,必須通過函數(shù)訪問。因?yàn)榻Y(jié)構(gòu)數(shù)據(jù)成員是公共的,所以它們可以被直接訪問,并且可以像常規(guī)變量一樣使用。以下語句即可為前面創(chuàng)建的每個(gè) PayRoll 變量的 empNumber 成員賦值:
  1. deptHead.empNumber = 475;
  2. foreman.empNumber = 897;
  3. associate.empNumber = 729;
以下語句將顯示 deptHead 變量所有成員的內(nèi)容:
  1. cout << deptHead.empNumber << endl;
  2. cout << deptHead.name << endl;
  3. cout << deptHead.hours << endl;
  4. cout << deptHead.payRate << endl;
  5. cout << deptHead.grossPay << endl;
下面的程序是使用 PayRoll 結(jié)構(gòu)體的完整程序。請(qǐng)注意,在 cin 語句、cout 語句和數(shù)學(xué)運(yùn) 算中,單個(gè)結(jié)構(gòu)體成員的用法和常規(guī)變量基本上是一樣的。
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <string>
  4. using namespace std;
  5. struct PayRoll
  6. {
  7. int empNumber; // Employee number
  8. string name; // Employee name
  9. double hours, // Hours worked
  10. payRate; // Hourly pay rate
  11. };
  12. int main()
  13. {
  14. PayRoll employee; // Employee is a PayRoll structure
  15. double grossPay; // Gross amount the employee earned this week
  16. cout << "Enter the employee1s number:";
  17. cin >> employee.empNumber;
  18. cout << "Enter the employee's name: ";
  19. cin.ignore();// Skip the '\n' character left in the input buffer
  20. getline(cin, employee.name);
  21. cout << "Hours worked this week: ";
  22. cin >> employee.hours;
  23. cout << "Employee's hourly pay rate: ";
  24. cin >> employee.payRate;
  25. // Calculate the employee's gross pay
  26. grossPay = employee.hours * employee.payRate;
  27. // Display the results
  28. cout << "\nHere is the employee1s payroll data:\n";
  29. cout << "Name: " << employee.name << endl;
  30. cout << "Employee number: " << employee.empNumber << endl;
  31. cout << "Hours worked: " << employee.hours << endl;
  32. cout << "Hourly pay rate: " << employee.payRate << endl;
  33. cout << fixed << showpoint << setprecision(2);
  34. cout << "Gross pay: $" << grossPay << endl;
  35. return 0;
  36. }
程序輸出結(jié)果:

Enter the employee1s number:2214
Enter the employee's name: Jack Smith
Hours worked this week: 40
Employee's hourly pay rate: 12.50

Here is the employee1s payroll data:
Name:   Jack Smith
Employee number: 2214
Hours worked:   40
Hourly pay rate: 12.5
Gross pay: $500.00

程序中,變量 employee 被定義在第 17 行,它是 Payroll 結(jié)構(gòu)體的一個(gè)實(shí)例。此后就可以通過變量名稱和點(diǎn)運(yùn)算符來訪問其中的 5 個(gè)數(shù)據(jù)成員。例如,在第 22 行中,以下語句將讀取變量的 empNumber 成員中的值:

cin >> employee.empNumber; //正確

如果試圖通過結(jié)構(gòu)體類型的名稱來訪問該成員,那么結(jié)果將是錯(cuò)誤的:

cin >> Payroll.empNumber; //錯(cuò)誤

結(jié)構(gòu)體嵌套

正如一個(gè)類的對(duì)象可以嵌套在另一個(gè)類中一樣,一個(gè)結(jié)構(gòu)體的實(shí)例也可以嵌套在另一個(gè)結(jié)構(gòu)體中。例如,來看以下聲明:
  1. struct Costs
  2. {
  3. double wholesale;
  4. double retail;
  5. };
  6. struct Item
  7. {
  8. string partNum;
  9. string description;
  10. Costs pricing;
  11. };
Costs 結(jié)構(gòu)體有兩個(gè) double 類型成員,wholesale 和 retail。Item 結(jié)構(gòu)體有 3 個(gè)成員,前 2 個(gè)是 partNum 和 description,它們都是 string 對(duì)象。第 3 個(gè)是 pricing,它是一個(gè)嵌套的 Costs 結(jié)構(gòu)體。如果定義了一個(gè)名為 widge t的 Item 結(jié)構(gòu)體,則圖 3 說明了其成員。

在 widget 的成員中包含一個(gè)嵌套結(jié)構(gòu)體
圖 3 在 widget 的成員中包含一個(gè)嵌套結(jié)構(gòu)體

它們可以按以下方式訪問:
  1. widget.partnum = "123A";
  2. widget.description = "iron widget";
  3. widget.pricing.wholesale = 100.0;
  4. widget.pricing.retail = 150.0;
請(qǐng)注意,wholesale 和 retail 不是 widget 的成員,pricing 才是。要訪問 wholesale 和 retail,必須首先訪問 widget 的定價(jià) pricing,然后由于它是一個(gè) Costs 結(jié)構(gòu)體,所以同樣可以使用點(diǎn)運(yùn)算符訪問其 wholesale 和 retail 成員。

還要注意,對(duì)于所有結(jié)構(gòu)體來說,訪問成員時(shí)必須使用成員名稱,而不是結(jié)構(gòu)體名稱。例如,以下語句不合法:
  1. cout << widget.retail; // 錯(cuò)誤
  2. cout << widget.Costs.wholesale; // 錯(cuò)誤
在決定是否使用嵌套結(jié)構(gòu)體時(shí),請(qǐng)考慮各種成員的相關(guān)性。一個(gè)結(jié)構(gòu)體將邏輯上屬于一體的項(xiàng)目綁定在一起。通常,結(jié)構(gòu)體的成員是描述某個(gè)對(duì)象的屬性。在上述示例中,對(duì)象是一個(gè) widget(小零部件),而 partNum(部件編號(hào))、description(描述)、wholesale(批發(fā))和 retail(零售)價(jià)格都是其屬性。

當(dāng)某些屬性相關(guān)并形成對(duì)象屬性的邏輯子組時(shí),將它們綁定在一起并使用嵌套結(jié)構(gòu)體是有意義的。請(qǐng)注意下面程序內(nèi)部結(jié)構(gòu)體中屬性的相關(guān)性,它使用了嵌套結(jié)構(gòu)體。
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <string>
  4. using namespace std;
  5. struct CostInfo
  6. {
  7. double food, // Food costs
  8. medical, // Medical costs
  9. license, // License fee
  10. misc; // Miscellaneous costs
  11. };
  12. struct PetInfo
  13. {
  14. string name; // Pet name
  15. string type; // Pet type
  16. int age; // Pet age
  17. CostInfo cost;
  18. PetInfo() // Default constructor
  19. {
  20. name = "unknown";
  21. type = "unknown";
  22. age = 0;
  23. cost.food = cost.medical = cost.license = cost.misc = 0.00;
  24. }
  25. };
  26. int main()
  27. {
  28. PetInfo pet;
  29. pet.name = "Sassy";
  30. pet.type = "cat";
  31. pet.age = 5;
  32. pet.cost.food = 300.00;
  33. pet.cost.medical = 200.00;
  34. pet.cost.license = 7.00;
  35. cout << fixed << showpoint << setprecision(2);
  36. cout << "Annual costs for my " << pet.age << "—year—old "<< pet.type << " " << pet.name << " are $"<< (pet.cost.food + pet.cost.medical +pet.cost.license + pet.cost.misc) << endl;
  37. return 0;
  38. }

程序輸出結(jié)果:
Annual costs for my 5-year-old cat Sassy are $507.00

將結(jié)構(gòu)體傳遞給函數(shù)

與類對(duì)象一樣,結(jié)構(gòu)體變量也可以通過值、引用和常量引用傳遞給函數(shù)。默認(rèn)情況下,它們通過值傳遞,這意味著需要生成整個(gè)原始結(jié)構(gòu)的副本并傳遞給函數(shù)。因?yàn)椴幌M速M(fèi)時(shí)間來復(fù)制整個(gè)結(jié)構(gòu)體,所以,除非結(jié)構(gòu)很小,否則一般會(huì)通過引用將結(jié)構(gòu)體傳遞給函數(shù)。但是,這樣意味著函數(shù)可以訪問原始結(jié)構(gòu)的成員變量,從而可能更改它們。如果不想讓函數(shù)更改任何成員變量值,那么可以考慮將結(jié)構(gòu)體變量作為一個(gè)常量引用傳遞給函數(shù)。

下面程序定義了一個(gè)結(jié)構(gòu)體變量并將其傳遞給了兩個(gè)函數(shù)。
  1. //程序1
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <string>
  5. using namespace std;
  6. struct Invltem// Holds data for an inventory item
  7. {
  8. int partNum; // Part number
  9. string description; // Item description
  10. int onHand; // Units on hand
  11. double price; // Unit price
  12. };
  13. // Function prototypes
  14. void getltemData(InvItem &) ;
  15. void showItem(const InvItem &);
  16. int main()
  17. {
  18. InvItem part; // Define an Invltem structure variable.
  19. getItemData(part);
  20. showItem(part);
  21. return 0;
  22. }
  23. void getItemData(InvItem &item)
  24. {
  25. cout << "Enter the part number: ";
  26. cin >> item.partNum;
  27. cout << "Enter the part description: ";
  28. cin.get();
  29. getline (cin, item.description);
  30. cout << "Enter the quantity on hand: ";
  31. cin >> item.onHand;
  32. cout << "Enter the unit price: ";
  33. cin >> item.price;
  34. }
  35. void showItem(const InvItem &item)
  36. {
  37. cout << fixed << showpoint << setprecision(2) << endl;
  38. cout << "Part Number : " << item.partNum << endl;
  39. cout << "Description : " << item.description << endl;
  40. cout << "Units On Hand : " << item.onHand << endl;
  41. cout << "Price : $" << item.price << endl;
  42. }
程序輸出結(jié)果:

Enter the part number: 800
Enter the part description: Screwdriver
Enter the quantity on hand: 135
Enter the unit price: 1.25

Part Number : 800
Description : Screwdriver
Units On Hand: 135
Price : $1.25

從函數(shù)返回一個(gè)結(jié)構(gòu)體

也可以從函數(shù)返回結(jié)構(gòu)體變量。在這種情況下,函數(shù)的返回類型是結(jié)構(gòu)體的名稱。可以改寫程序 1 以允許 getItemData 函數(shù)創(chuàng)建 Invltem 結(jié)構(gòu)體的局部實(shí)例,將數(shù)據(jù)值放入其成員變量中,然后將其傳遞回 main,而不是將其作為引用變量從 main 接收。

以下是修改后的 getltemData 函數(shù)的樣子:
  1. InvItem getItemData()
  2. {
  3. InvItem item;
  4. cout << "Enter the part number:";
  5. cin >> item.partNum;
  6. cout << "Enter the part description: ";
  7. cin.get();
  8. getline(cin, item.description);
  9. cout << "Enter the quantity on hand: ";
  10. cin >> item.onHand;
  11. cout << "Enter the unit price: ";
  12. cin >> item.price;
  13. return item;
  14. }
以下是從 main 中調(diào)用它的方法:

part = getItemData();

注意,C++ 只允許從函數(shù)返回單個(gè)值。然而,結(jié)構(gòu)體提供了解決這一限制的方法。即使一個(gè)結(jié)構(gòu)體可能有幾個(gè)成員,它在技術(shù)上還是一個(gè)單一的對(duì)象。通過在結(jié)構(gòu)體中打包多個(gè)值,可以從函數(shù)返回任意數(shù)量的值。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多