class和struct的區別
我們可以使用class 和struct 的任何一個來定義類,唯一的一點區別就是struct和class的訪問權限不太一樣。
當我們希望定義的類的所有成員是publ的是,使用struct,反之,如果希望成員是private的,使用class
friend 友元
類可以允許其他類或者函數訪問他的非公有成員,方法是領其他類或者函數稱爲他的友元。
class Sales_data {
//聲明爲友元
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
public:
// 構造函數
Sales_data() = default;
Sales_data(const std::string &s): bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p):
bookNo(s), units_sold(n), revenue(p*n) { }
Sales_data(std::istream &);
//
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
private:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
//Sales_data接口的非成員組成部分
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);
友元的聲明只能出現在類定義的內部。友元的聲明僅僅指定了訪問的權限,而非一個普通意義上的函數聲明。如果我們希望類的用戶能夠調用某個友元函數,那麼我們就必須在友元聲明之外再專門對函數進行一次聲明。
類之間的友元關係
舉個例子,我們的Window_mgr類的某些成員可能需要訪問它管理的Screen類的內部數據。例如,我們需要爲Window_mgr添加一個名爲clear的成員,它負責吧一個指定的Screen的內容設置爲空白,爲了完成這一任務,clear需要訪問Screen的私有成員,而想要另這種訪問合法,Screen需要把Window_mgr指定爲它的友元。
class Screen{
//Window_mgr 的成員可以訪問Screen類的私有部分
friend class Window_mgr;
//Screen類的剩餘部分
}
友元關係不具有傳遞性,也就是說,如果Window_mgr有它自己的友元,則這些友元並不能理所淡然的具有訪問Screen的特權。
令成員函數作爲友元
除了讓整個Window_mgr作爲友元之外,Screen還可以只爲clear提供訪問權限。當把一個成員函數聲明爲友元時,我們必須明確指出該成員函數屬於哪個類。
class Screen{
//Window_mgr::clear 必須在Screen類之前被聲明
friend void Window_mgr::clear(ScreenIndex);
//Screen類的剩餘部分
}
友元聲明和作用域
即使我們僅僅是用聲明友元的類的成員調用該函數,它也必須是被聲明過的。
struct X{
friend void f(){//友元函數可以定義在類的內部}
X(){
f();//錯誤,f還沒有被聲明
}
void g();
void h();
};
void X::g(){return f();}//錯誤,f還沒有被聲明
void f();//聲明哪個定義在X中的函數
void X::h(){return f();}//正確:現在f的聲明在作用域中了