一、友元函數的概念
在C++中,一個類可以將其一些私有成員賦予其它的類或者函數訪問許可權,稱為友元函數。
class A { private: int x; void sayHi() { std::cout << "Hi, I'm A." << std::endl; } friend void B::print(A a); }; class B { public: void print(A a) { std::cout << a.x << std::endl; // a.x可以訪問,因為B是A的友元類 a.sayHi(); // a.sayHi()可以訪問,因為B是A::sayHi()的友元函數 } };
在上面的代碼中,A將print函數聲明為友元函數,使其可以訪問A的私有成員x和sayHi函數。在B的print函數中,也可以調用A的sayHi函數。
二、友元函數的作用
友元函數可以解決某些場景下的訪問限制問題。
三、友元函數與運算符重載
另一個常見的友元函數使用場景是運算符重載。在運算符重載中,為了讓函數能夠訪問類的私有數據成員,需要將這個函數聲明為類的友元函數。
class Rational { public: Rational(int a = 0, int b = 1) : num(a), den(b) {} friend Rational operator+(Rational r1, Rational r2) { return Rational(r1.num * r2.den + r2.num * r1.den, r1.den * r2.den); } private: int num; int den; };
在上面的代碼中,將operator+函數聲明為Rational的友元函數,使其可以訪問Rational的私有成員num和den。這樣,+運算符才能正確地計算兩個有理數的和。
四、友元類
除了友元函數,C++還有另一個友元概念:友元類。友元類是指在類中聲明另一個類為友元,使其能夠訪問當前類的私有成員。
class A { friend class B; private: int x; }; class B { public: void print(A a) { std::cout << a.x << std::endl; // 可以訪問A的私有成員x } };
在上面的代碼中,A將B聲明為友元類,使其能夠訪問A的私有成員x。
五、友元函數的缺點
儘管友元函數有一些好處,但過度使用友元函數會破壞類的封裝性,使類中的私有成員變得透明,降低代碼的可維護性和可復用性。
六、友元類與繼承
當類B是類A的友元類時,B可以訪問A的私有成員。如果類C繼承類A,且將B聲明為其友元類,那麼B也可以訪問C的私有成員。
class A { friend class B; private: int x; }; class C : public A { friend class B; private: int y; }; class B { public: void print(A a) { std::cout << a.x << std::endl; // 可以訪問A的私有成員x } void print(C c) { std::cout << c.x << " " << c.y << std::endl; // 可以訪問C的私有成員x和y } };
七、友元函數的例子:矩陣乘法
友元函數的另一個常見使用場景是在矩陣類中實現矩陣乘法。在矩陣乘法中,需要訪問另一個矩陣的私有成員,因此需要將矩陣乘法函數聲明為矩陣類的友元函數。
class Matrix { public: Matrix(int r = 0, int c = 0) : rows(r), cols(c) { data = new int[rows * cols]; } Matrix(const Matrix& m) : rows(m.rows), cols(m.cols) { data = new int[rows * cols]; std::copy(m.data, m.data + rows * cols, data); } ~Matrix() { delete[] data; } friend Matrix operator*(const Matrix& m1, const Matrix& m2) { assert(m1.cols == m2.rows); Matrix res(m1.rows, m2.cols); for (int i = 0; i < m1.rows; ++i) { for (int j = 0; j < m2.cols; ++j) { int sum = 0; for (int k = 0; k < m1.cols; ++k) { sum += m1.data[i * m1.cols + k] * m2.data[k * m2.cols + j]; } res.data[i * res.cols + j] = sum; } } return res; } private: int rows; int cols; int* data; };
在上面的代碼中,將operator*函數聲明為Matrix的友元函數,使其可以訪問另一個矩陣的私有成員。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/302055.html