程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++啟蒙之C++中的類

C++啟蒙之C++中的類

編輯:關於C++

在解決我們的書店問題之前,我們需要理解的唯一的剩余問題是如何編寫一個數據結構(data structure)來表示我們的事務數據。在C++中我們通過定義類(class)來定義自己的數據結構。類機制是C++中最重要的特性之一。實際上,C++設計的主要聚焦點是使我們能夠定義類類型(class types),使它的操作與內建類型一樣自然。我們已經看到了類庫類型(例如istream和ostream),它們都是作為類定義的--也就是說,嚴格地說,它們並不是語言的一部分。

完整地理解類機制需要掌握大量的信息。幸運的是,我們可以使用其他人編寫的類而不需要知道自己如何定義類。在這一部分,我們將介紹一個簡單的類,我們可以利用它來解決書店問題。

要使用某個類,我們必須知道三種信息:

1.它的名稱是什麼?

2.它是在哪兒定義的?

3.它支持哪些操作?

對於我們的書店問題,我們假設這個類叫做Sales_item,它是在一個叫做Sales_item.h的頭文件中定義的。

1、Sales_item類

Sales_item類的目的是存儲一個ISBN並跟蹤該書的銷售數量、收入和平均售價。這些數據如何存儲和計算是我們關心的問題。要使用一個類,我們不必知道它實現的細節信息。作為代替,我們只需要知道它所支持的操作。

我們已經看到,我們使用類似IO的類庫工具的時候,我們必須包含相關的頭文件。類似地,對於我們自己的類,我們也必須讓編譯器知道與類相關的定義。實現這樣的功能的操作與前面的操作是相同的。典型情況下,我們把類定義放在一個文件中。任何希望使用我們的類的程序都必須包含這個文件。

按照慣例,類定義存儲在一個文件中,與程序源文件的名字類似,它的名字有兩個部分:文件名和擴展名。通常文件名與類的名字相同。擴展名通常是.h,但是有些程序員使用.H、.hpp或.hxx。編譯器一般對頭文件名稱不太挑剔,但是有的IDE會挑剔的。我們假設自己的類定義在Sales_item.h文件中。

Sales_item對象上的操作

每個類都定義了一個類型。這種類型的名稱與類的名稱相同。因此,我們的Sales_item類定義了Sales_item類型。與內建類型相似,我們可以定義類類型變量。當我們編寫

Sales_item item;

我們就說是一個Sales_item類型的對象。我們通常約定"類型Sales_item的一個對象"等於"一個Sales_item對象"或簡單地說"一個Sales_item"。

作為定義類型Sales_item的變量的補充,我們可以執行Sales_item對象上的如下一些操作:

· 使用加號操作符(+)把兩個Sales_item進行相加

· 使用輸入操作符(<<)讀取Sales_item對象

· 使用輸出操作符(>>)寫入Sales_item對象

· 使用賦值操作符(=)把Sales_item對象賦給另外一個

· 調用same_isb函數檢測是否兩個Sales_item指向同一本書

讀取和寫入Sales_item

現在我們知道了該類提供的操作,我們可以編寫一些簡單的程序來使用這個類了。例如,下面的程序從標准輸入中讀取數據,使用這些數據來建立Sales_item對象,並把該Sales_item對象寫回標准的輸出中:

#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item book;
// 讀取ISBN、銷售數量和售價
std::cin >> book;
// 寫入ISBN、銷售數量、總收入和平均售價
std::cout << book << std::endl;
return 0;
}

如果這個程序的輸入信息是:

0-201-70353-X 4 24.99

那麼它的輸出信息是:

0-201-70353-X 4 99.96 24.99

輸入信息說明我們銷售了四本書,每本$24.99,輸出信息表明總共銷售了四本,總共的收入是$99.96,平均售價是$24.99。

這個程序以兩個#include指令開始,其中一個使用了新的形式。Iostream頭文件是標准類庫定義的;Sales_item頭文件不是標准類庫定義的。Sales_item是我們自己定義的類型。當我們使用自己的頭文件的時候,需要使用引號(" ")包含頭文件名稱。

注意:

標准類庫的頭文件是使用尖括號(< >)包含的。非標准的頭文件使用引號(" ")包含。

在main中我們先定義了一個對象,叫做book,我們將使用它來保存那些從標准輸入中讀取的數據。下一個語句把輸入讀取該對象,第三個語句把它打印到標准的輸出中,接著打印endl來刷新緩沖器。

類定義的行為

我們使用Sales_item的時候,要記住Sales_item類的作者定義了這個類的對象能夠執行的全部操作。也就是說,Sales_item數據結構的作者定義了Sales_item對象建立的時候發生什麼事情,在Sales_item對象上應用加、輸入、輸出等操作的時候發生什麼情況,等等。一般來說,只有類所定義的操作才能在類類型的對象上使用。

兩個Sales_item相加

兩個Sales_item對象相加的例子稍微有趣一些:

#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item item1, item2;
std::cin >> item1 >> item2; // 讀取兩個事務記錄
std::cout << item1 + item2 << std::endl; // 輸出它們的和
return 0;
}

如果我們給這個程序輸入下面的信息:

0-201-78345-X 3 20.00

0-201-78345-X 2 25.00

輸出結果是:

0-201-78345-X 5 110 22

這個程序先包含了Sales_item和iostream頭文件。接著我們定義了兩個Sales_item對象來保存我們希望匯總的兩個事務。輸出表達式執行加法操作並打印結果。我們知道兩個Sales_item相加將建立一個新對象,它的ISBN為自己的操作數,售價和收入則反映了操作數中的相關值。我們還知道相加的項目必須有相同的ISBN。

上面的程序中有趣的地方是,我們不是讀取並打印兩個整數的和,而是讀取並打印兩個Sales_item對象的和。此外,求和的想法也是不同的。在使用整數的情況下我們生成傳統的和--就是兩個數值相加的結果。在使用Sales_item對象的時候,求和有新的意義--兩個Sales_item對象相加的結果。

練習21:

Web站點包含了Sales_item.h的副本。把它復制到你的工作目錄中。編寫一個程序,在圖書銷售事務記錄中進行循環,讀取每個事務並把它寫入標准的輸出。

練習22:

編寫一個程序,讀取兩個擁有相同的ISBN的Sales_item對象並生成它們的和。

練習23:

編寫一個程序讀取ISBN相同的幾個事務記錄,寫出它們的和。

2、初探成員函數

不幸的是,Sales_item相加的程序有個問題。如果你的輸入信息使用了兩個不同的ISBN會發生什麼情況呢?它沒有辦法處理兩個不同ISBN的數據相加。為了解決這個問題,我們將首先檢查Sales_item操作數是否有相同的ISBN:

#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item item1, item2;
std::cin >> item1 >> item2;
// 檢查 item1 和 item2 是否是同一本書
if (item1.same_isbn(item2)) {
std::cout << item1 + item2 << std::endl;
return 0; //表示成功
} else {
std::cerr << "Data must refer to same ISBN"
<< std::endl;
return -1; // indicate failure
}
}

這個程序與前面的程序之間的區別在於if條件和相關的else分支。在解釋if條件之前,我們知道程序的操作依賴於if中的條件。如果測試成功,那麼我們寫出與前面的程序相同的輸出信息,並且返回0表明成功了。如果測試失敗,我們執行else後面的代碼塊,它打印一條消息並返回錯誤標識符。

成員函數是什麼?

If條件

if (item1.same_isbn(item2)) {

調用了Sales_item對象item1的成員函數。成員函數是類定義的函數。成員函數有時候也稱為類的方法。

成員函數只在類中一次定義,但是每個對象都把它作為成員來處理。我們把這種操作稱為成員函數是因為它們(通常)在特定的對象上操作。在例子中,它們都是對象的成員,即使單個定義也被相同類型的所有對象所共享。

當我們調用成員函數的時候,我們(通常)指定該函數在哪個對象上操作。其語法是使用點操作符("."):

item1.same_isbn

它的意思是"item1對象的same_isbn成員"。點操作符從它的左邊取得右邊的操作數。點操作符指定應用於類類型的對象:左邊的操作數必須是類類型的對象;右邊必須是該類型的成員的名稱。

注意:

與大多數操作符不同,點操作符右邊的操作數並不是對象或值;它是成員的名稱。

當我們把成員函數作為右邊的操作數的時候,我們通常是調用這個函數。我們執行成員函數的方式與執行其它函數的方式相同:要調用函數,我們在函數名稱後面加上調用操作符("()"操作符)。調用操作符是一對括號,它封裝了傳遞進該函數的參數列表(可能是空的)。

same_isbn函數只有一個參數,這個參數是另一個Sales_item對象。下面的調用

item1.same_isbn(item2)

把item2作為參數傳遞進same_isbn函數,而這個函數是item1對象的一個成員。這個函數把參數item2中的ISBN部分與item1(調用same_isbn的對象)的ISBN進行比較。因此,其效果是測試兩個對象的ISBN是否相同。

如果它們的ISBN相同,我們就執行if後面的語句,打印兩個Sales_item對象相加的結果。否則,如果ISBN不同,我們將執行else分支,它也是一個代碼塊。這個代碼塊打印適當的錯誤信息並退出程序,返回-1。請回憶一下,main的返回值是被當作狀態標識的。在例子中,返回非零的值表明程序生成預想的結果失敗了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved