訪問說明符可以控制類中的成員的訪問權限。
使用public修飾的類的成員,類的用戶可以直接訪問。
使用private修飾的類的成員,只有成員函數可以訪問,類的用戶是沒法訪問的。
C++沒有限制類中定義訪問說明符的數量和位置,可以隨處添加,一個訪問說明符的修飾範圍是,它聲明的位置開始到類的下一個訪問說明符。
C++中有兩個關鍵字可以定義類,就是class和struct,他們的唯一區別在於class定義類的默認的訪問權限是private,struct定義的類默認的訪問權限是public。
練習
7.16
沒有數量和位置的限制,如果成員函數或者數據成員需要讓類的使用者顯式的使用,那麼就是用public訪問說明符,一般情況下,數據成員都是private,還有一些僅在類內部使用的函數也可以使用private訪問限定符修飾
7.17
默認的訪問權限不一樣
7.18
封裝就是隱藏細節,封裝可以讓用戶無需關注類的實現細節,直接調用接口。這還在一定程度上保證了類的安全性,讓類的使用者不能直接修改某些數據成員。
7.19
struct Person {
private:
string name;
string address;
public:
string get_info()const{
return "name:" + name + "\n address:" + address;
}
Person(const string &n, const string &address) :name(n), address(address) {};
};
爲了防止用戶隨意修改數據成員,所以數據成員都使用private訪問限定符
而成員函數則使用public。
7.2.1 友元
一般情況下,數據成員會聲明爲private,這樣在使用類的代碼時,用戶時無法直接訪問數據成員的。
但是對於某些函數,它是類的接口,卻不是類的成員,這些類往往會直接訪問類的數據成員。爲了解決在類的外部無法訪問private修飾的數據成員和成員函數。
C++提供了友元friend
如果把一個函數在類中聲明爲友元,那麼這個函數就可以直接訪問了類的private修飾的成員了。
就像這樣。
struct Person {
friend istream &input(istream& temp_cin, Person& p);
friend ostream & print(ostream& temp_cout, const Person &p);
private:
string name;
string address;
public:
string get_info()const{
return "name:" + name + "\n address:" + address;
}
Person()=default;
Person(const string &n, const string &address) :name(n), address(address) {};
};
istream &input(istream& temp_cin, Person& p) {
temp_cin >> p.name >> p.address;
return temp_cin;
}
ostream & print(ostream& temp_cout,const Person &p) {
temp_cout << p.name << "," << p.address << endl;
return temp_cout;
}
要注意的是,friend修飾的外部函數,僅僅表示i這個函數是友元的,不算是聲明,所以需要在類的外部單獨的聲明。。
練習
7.20
如果某一個外部函數需要調用類的private成員,就需要將該函數聲明爲這個類的友元函數。
好處在於,對於某些是類的接口,卻不是類的成員函數的函數,可以直接訪問類的數據成員。
壞處在於,這等於在破壞封裝性,友元函數可以直接訪問類的private成員,帶來了不安全性。
7.21
struct Sales_data
{
friend istream& input(istream& temp_input, Sales_data& data);
friend ostream& print(ostream& temp_cout, const Sales_data& data);
friend Sales_data add(Sales_data &data1, const Sales_data & data2);
private:
string bookNo;
unsigned units_sold=0;
double revenue = 0.0;
public:
string isbn() const { return bookNo; };
Sales_data& combine(const Sales_data& );
double avg_price()const;
//構造函數
//1.默認構造函數
Sales_data() =default;
//2.僅初始化isbn
Sales_data(const string& isbn) :bookNo(isbn) {};
//3.數據成員都初始化
Sales_data(const string& isbn, unsigned u, double p) :bookNo(isbn), units_sold(u), revenue(u*p) {};
//4.使用流來初始化
Sales_data(istream& temp_input) {
input(temp_input,*this);
};
};
7.22
上面總結中的代碼就是