第七章 類
類的基本思想是數據抽象和封裝。
數據抽象是一種依賴於接口和實現分離的變成技術。
- 類的接口包括用戶所能執行的操作
- 類的實現則包括類的數據成員、負責接口實現的函數體以及定義類所需要的各種私有函數。
7.1 定義抽象數據類型
下面以 Sales_itme類和Sales_data類對抽象類型進行解釋
7.1.1 設計Sales_item
#include <iostream>
#include <string>
using namespace std;
struct Sales_data
{
string isbn;
unsigned unit_solid = 0;
double revenue = 0.0;
Sales_data& read(istream& is) {
Sales_data sale_data;
cout << "please input the isbn:" << endl;
string s_isbn;
char *c_isbn=new char[sizeof(s_isbn)];
is.getline(c_isbn,sizeof(s_isbn));
s_isbn=c_isbn;
sale_data.isbn = s_isbn;
cout << "please input the unit_sold:" << endl;
char *c_unit_solid = new char[sizeof(c_unit_solid)];
is.getline(c_unit_solid, sizeof(s_isbn));
unsigned unit_solid = atoi(c_unit_solid);
sale_data.unit_solid = unit_solid;
cout << "please input the revenue:" << endl;
char *c_revenue = new char[sizeof(c_unit_solid)];
is.getline(c_unit_solid, sizeof(s_isbn));
double revenue = atof(c_unit_solid);
sale_data.revenue = revenue;
return sale_data;
}
void print(ostream os) {
}
};
簡單寫了個例子,感覺書本上面的例子有點複雜了
有類的抽象定義可以確定 Sales_data不是一個抽象數據類型,它允許類的用戶直接訪問他的數據成員,並且要求用戶來編寫操作。
7.1.2 定義改進的Sales_data類
把定義寫在頭文件中
struct Sales_data
{
//新成員:關於Sales_data對象的操作
string isbn() const {return bookNo;}
Sales_data& combine(const Sales_data&);
double avg_price() const;
}
//Sales_data的非成員接口函數
Sales_data add(const Sales_data&,const Sales_data&);
- 定義成員函數
成員函數體可以定義在類內也可以定義在類外。 - 引入this
在isbn()函數中只有一條return 語句,其實默認使用的this指針,可以理解爲
isbn(Sales_data& this)。 - 引入const成員函數
string isbn() const {return bookNo;} 在isbn()之後緊跟了一個const關鍵字,這裏const的作用是修改隱式this指針的類型。
在成員函數中,this的類型是Sales_data *this。儘管this是隱式的,但他仍然需要遵循初始化規則,意味着我們不能把this綁定到一個常量對象上。
加上const之後,表示this是一個指向常量的指針。想這樣使用const的成員函數被稱作常量成員函數
可以理解爲:
string Sales_data::isbn(const Sales_data *const this){return this->isbn};
常量對象,以及常量對象的引用或指針都只能調用常量成員函數。
7.1.3 定義類相關的非成員函數
- 定義read和print函數
isstream &read(istream &is,Sales_data &item)
{
double price=0;
}
7.1.4 構造函數
每個類都分別定義了他的對象初始化的方式,類通過一個或幾個特殊的成員函數來控制其對象的初始化過程,這些函數叫做構造函數。
struct Sales_data
{
Sales_data()=default //默認構造函數
Sales_data(const string& isbn):bookNo(isbn){} //用isbn初始化bookNo
}
7.2 訪問控制和封裝
- 訪問說明符
- 定義在public說明符之後的成員在整個程序內可被訪問,public成員定義類的接口。
- 定義在private說明符之後的成員可以被類的成員函數訪問,但是不能被使用該類的代碼訪問,private部分封裝了類的實現細節。
class Sales_data{
public: //添加了訪問說明符
Sales_data()=default;
Sales_data(const string &isbn, unsigned units_sold, double revenue):bookNo(isbn),units_sold(units_sold),revenue(revenue*units_sold){}
Sales_data(const string &isbn):bookNo(isbn){}
string isbn() const {return bookNo;}
Sales_data &combine(const Sales_data&);
private: //添加了訪問說明符
double avg_price() const {return units_sold?revenue/units_sold:0;}
string bookNo;
unsigned units_sold=0;
double revenue=0.0;
}
- 使用class或struct關鍵字
struct和class的默認訪問權限不太一樣,類可以在它的第一個訪問說明符之前定義成員,對這種成員的訪問權限依賴於類定義的方式。- 如果我們使用struct關鍵字,則定義在第一個訪問說明符之前的成員是public
- 如果我們使用class關鍵字,則這些成員是private的
使用class和struct定義類唯一的區別就是默認的訪問權限
7.2.1 友元
類可以允許其他類或者函數訪問他的非公有成員,方法是令其他類或者函數稱爲它的友元。
class Sales_data{
//爲Sales_data的非成員函數所有的友元聲明
friend Sales_data add(const Sales_data&,const Sales_data&);
friend istream &read(std::istream&,Sales_data&);
friend ostream &print(std::ostream&,const Sales_data&);
//其他成員及訪問說明符與之前一致
public:
Sales_data()=default;
Sales_data(const std::string &isbn,unsigned unit_sold,double revenue):bookNo(isbn),unit_sold(unit_sold),revenue(revenue*unit_sold){}
private:
std::string bookNo;
unsigned unit_sold=0;
double revenue=0.0;
};
類的用法和struct用法一樣,可以參考struct