一、友元介紹我們知道,類的成員函數可以訪問同類的其他成員函數,包括公有、私有和保護成員。而類的外部函數只能訪問類的公有成員。友元是一種允許非類成員函數訪問類的非公有成員的一種機制。可以把一個函數指定為類的友元,也可以把整個類指定為另一個類的友元。
友元函數友元類
二、友元函數友元函數在類作用域外定義,但它需要在類體中進行說明為了與該類的成員函數加以區別,定義的方式是在類中用關鍵字friend說明該函數,格式如下:
friend 類型 友元函數名(參數表);友元的作用在于提高程序的運行效率
友元函數注意事項:1、友元函數不是類的成員函數,在函數體中訪問對象的成員,必須用對象名加運算符“.”加對象成員名。但友元函數可以訪問類中的所有成員(公有的、私有的、保護的),一般函數只能訪問類中的公有成員。
2、友元函數不受類中的訪問權限關鍵字限制,可以把它放在類的公有、私有、保護部分,但結果一樣。
3、某類的友元函數的作用域并非該類作用域。如果該友元函數是另一類的成員函數,則其作用域為另一類的作用域,否則與一般函數相同。
4、友元函數破壞了面向對象程序設計類的封裝性,所以友元函數如不是必須使用,則盡可能少用。或者用其他手段保證封裝性。
代碼如下:#include <math.h>#include <iostream>using namespace std;class Point{ friend double Distance(const Point &p1, const Point &p2);public: Point(int x, int y);PRivate: int x_; int y_;};Point::Point(int x, int y) : x_(x), y_(y){}double Distance(const Point &p1, const Point &p2){ double dx = p1.x_ - p2.x_; double dy = p1.y_ - p2.y_; return sqrt(dx * dx + dy * dy);}int main(void){ Point p1(3, 4); Point p2(6, 9); cout << Distance(p1, p2) << endl; return 0;}程序中Distance 是Point類的友元函數,可以訪問類的私有數據成員。三、友元類如果某類B的成員函數會頻繁的存取另一個類A的數據成員, 而A的數據成員的Private/Protectd限制造成B存取的麻煩, B只能通過A的Public的成員函數進行間接存取把B做成A類的友元類,即A類向B類開放其Private/Protectd內容, 讓B直接存取友元類:一個類可以作另一個類的友元友元類的所有成員函數都是另一個類的友元函數友元類的聲明:friend class 類名;
友元類注意事項:1、友元關系是單向的2、友元關系不能被傳遞3、友元關系不能被繼承
TeleController.h :
代碼如下:
#ifndef _TELE_CONTROLLER_H_#define _TELE_CONTROLLER_H_class Television;class TeleController{public: void VolumeUp(Television &tv); void VolumeDown(Television &tv); void ChanelUp(Television &tv); void ChanelDown(Television &tv);};#endif // _TELE_CONTROLLER_H_ TeleController.cpp :代碼如下:#include "TeleController.h"#include "Television.h"void TeleController::VolumeUp(Television &tv){ tv.volume_ += 1;}void TeleController::VolumeDown(Television &tv){ tv.volume_ -= 1;}void TeleController::ChanelUp(Television &tv){ tv.chanel_ += 1;}void TeleController::ChanelDown(Television &tv){ tv.volume_ -= 1;} Television.h:代碼如下:#ifndef _TELEVISION_H_#define _TELEVISION_H_class TeleController;class Television{ friend class TeleController;public: Television(int volume, int chanel);private: int volume_; int chanel_;};#endif // _TELEVISION_H_Television.cpp:代碼如下:#include "Television.h"Television::Television(int volume, int chanel) : volume_(volume), chanel_(chanel){} main.cpp:代碼如下:#include "Television.h"#include "TeleController.h"#include <iostream>using namespace std;int main(void){ Television tv(1, 1); TeleController tc; tc.VolumeUp(tv); return 0;}將TeleController 類作為Television類的友元類,這樣TeleController 類的成員函數就都可以訪問Television類的所有成員,包括私有2.嵌套類概念:
所謂嵌套類,就是在類中聲明的類。如下代碼中,類Inner就是一個嵌套類,類Outer是外圍類:
class Outer{ class Inner { std::string m_strInner; }; std::string m_strOuter;};可見性:
嵌套類對于外圍類:
嵌套類僅僅是聲明在外圍類內部的類型,而不是外圍類的成員
外圍類不具備嵌套類所定義的成員
對于外圍類來說,嵌套類和其他的類沒有任何區別;外圍類能訪問嵌套類對象的public成員,不能訪問嵌套類對象的protected及private成員
外圍類對于嵌套類:
嵌套類不具備外圍類所定義的成員
嵌套類能訪問外圍類的public成員,不能訪問外圍類的protected及private成員
嵌套類對于外圍類外部的作用域:
無論嵌套類聲明為public、protected還是private,嵌套類對于外圍類任何成員可見
當嵌套類在外圍類中聲明為public時,對外圍類之外的作用域可見,外圍類之外的作用域可通過“::”訪問嵌套類;
以下代碼正確無誤,輸出“I an inner”
#include <iostream>#include <string>class Outer{public: class Inner { public: Inner():m_strInner("I an inner") { } void PrintInner() { printf("%s", m_strInner.c_str()); } private: std::string m_strInner; };};int main(void){ Outer::Inner inner; inner.PrintInner(); getchar(); return 0;}當嵌套類在外圍類中聲明為protected或private時,對外圍類之外的作用域不可見
以下代碼編譯錯誤
include <iostream>#include <string>class Outer{ class Inner { public: Inner():m_strInner("I an inner") { } void PrintInner() { printf("%s", m_strInner.c_str()); } private: std::string m_strInner; };};int main(void){ Outer::Inner inner; inner.PrintInner(); getchar(); return 0;}繼承性:
下面列出了嵌套類在基類中三種訪問屬性和繼承的三種方式共9總組合,繼承之后嵌套類在派生類中的訪問屬性

結合1和上文的“可見性”就可得出當派生類作為嵌套類的外圍類,嵌套類和外圍類之間,嵌套類和外圍類之外的作用域之間的可見性了;這里就不一一列舉,留給讀者自己去驗證
新聞熱點
疑難解答
圖片精選