一、友元函數的概念
在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-hk/n/302055.html
微信掃一掃
支付寶掃一掃