1. 友元函數
友元函數引入:
-
私有成員對於類外部的所有程序部分而言都是隱藏的,訪問它們需要調用一個公共成員函數,但有時也可能會需要創建該規則的一項例外。
-
友元函數是一個不屬於類成員的函數,但它可以訪問該類的私有成員。換句話說,友元函數被視爲好像是該類的一個成員。友元函數可以是常規的獨立函數,也可以是其他類的成員。實際上,整個類都可以聲明爲另一個類的友元。
-
爲了使一個函數或類成爲另一個類的友元,必須由授予它訪問權限的類來聲明。類保留了它們的朋友的 “名單”,只有名字出現在列表中的外部函數或類才被授予訪問權限。通過將關鍵字 friend 放置在函數的原型之前,即可將函數聲明爲友元。
友元函數說明
- 必須在類的說明中說明友元函數,說明時以關鍵字friend開頭,後跟友元函數的函數原型,友元函數的說明可以出現在類的任何地方,包括在private和public部分;
- 注意友元函數不是類的成員函數,所以友元函數的實現和普通函數一樣,在實現時不用"::“指示屬於哪個類,只有成員函數才使用”::"作用域符號;
- 友元函數不能直接訪問類的成員,只能訪問對象成員,
- 友元函數可以訪問對象的私有成員,但普通函數不行;
- 調用友元函數時,在實際參數中需要指出要訪問的對象,
- 類與類之間的友元關係不能繼承。
- 一個類的成員函數也可以作爲另一個類的友元,但必須先定義這個類。
2. 訪問私有成員的3種情況
No.1
- 說明: 一個全局函數想訪問一個類對象的私有成員
- 解決方法: 在該類中把那個全局函數定義爲該類的友元函數
- 舉例:
#include<iostream> #include <math.h> using namespace std; class Point { int x, y; public: Point(int x= 0, int y = 0); void disp(); // 友元函數的聲明 friend double dist(Point p1, Point p2); }; Point::Point(int x, int y) { this->x = x; this->y = y; } void Point::disp() { cout << '(' << x << ',' << y << ')' << endl;} // 因訪問類對象的私有屬性,在類中定義友元函數 double dist(Point p1, Point p2) { double x = p1.x - p2.x; double y = p1.y - p2.y; return sqrt(x*x+y*y); } int main() { Point p1(0,0), p2(1,1); double dis = dist(p1,p2); cout << "distance of p1 and p2: " << dis << endl; system("pause"); return 0; }
No.2
- 說明: 一個類中的成員函數想訪問另一個類對象的私有成員
- 解決方法: 可以在被訪問對象類中定義該函數爲友元函數
- 舉例:
#include<string> #include<iostream> using namespace std; class Teacher; // 聲明類 class Student { string name; int age; int score; public: Student(){}; Student(string name="onname", int age=18); void disp(); // 定義Teacher類的setScore成員函數爲該類的友元函數 friend void Teacher::setScore(Student &s, int score); }; Student::Student(string name, int age) { this->name = name; this->age = age; score = 0; } void Student::disp() { cout << "I am a student!" << endl; cout << name << " " << age << " " << score << endl; } class Teacher { string name; int age; public: Teacher(){}; Teacher(string name="onname", int age=30); void disp(); // 爲了改變學對象的成績,使用引用類型 void setScore(Student &s, int score); }; Teacher::Teacher(string name, int age) { this->name = name; this->age = age; } void Teacher::disp() { cout << "I am a teacher!" << endl; cout << name << " " << age << endl; } // 因要訪問別的類對象的私有成員,需定義友元函數 void Teacher::setScore(Student &s, int score) { s.score = score; } int main() { Teacher t = Teacher("Jack"); t.disp(); Student s = Student("Mary", 19); s.disp(); // 老師修改學生成績 t.setScore(s,90); t.disp(); return 0; }
No.3
- 說明: 一個類中的一個對象想訪問同類中的另一個對象的私有成員,可直接訪問
- 舉例
#include<iostream> using namespace std; class Complex { private: int real, imag; public: Complex(int r = 0, int i = 0); void disp(); void input(); Complex operator+(Complex c); }; Complex::Complex(int r, int i) { this->real = r; this->imag = i; } void Complex::disp() { cout << real << " " << imag << endl; } Complex Complex::operator+(Complex c) { // 直接用傳入對象的私有屬性,將它們實部和虛部分別相加後再利用構造函數創建新對象返回 return Complex(real+c.real,imag + c.imag); } int main() { Complex c1(2,3), c2(2,-3), c3; c3.disp() c3 = c1 + c2; c3.disp(); return 0; }