C++中的友元类和函数
Friend Class,一个 friend 类可以访问它被声明为 friend 的其他类的私有和受保护成员。
允许特定类访问其他类的私有成员有时很有用。例如,可以允许 LinkedList 类访问 Node.js 的私有成员。
友元类可以访问它在其中被声明为友元的类的私有成员和受保护成员。
1、类做友元
将链表的节点定义为一个类:
class Node {
private:
int key;
Node* next;
/* Other members of Node Class */
// Now class LinkedList can
// access private members of Node
friend class LinkedList;
};
举个例子:
#include <iostream>
using namespace std;
class Node {
friend class LinkedList; //声明LinkedList类是Node的一个友元,这样LinkedList就可以直接访问Node中的成员
private:
int val;
Node* next;
public:
Node(): val(0), next(nullptr){}
Node(int v): val(v), next(nullptr){}
};
class LinkedList {
private:
Node* head;
public:
LinkedList(): head(nullptr){}
LinkedList(int v): head(new Node(v)){}
int getHeadValue(){ //访问节点head中的值(之前val是private的,只能在Node类中进行访问,但是在Node类中定义了LinkedList类是他的一个友元,这样LinkedList也可以访问Node中的私有成员)
return head->val;
}
};
int main() {
LinkedList* h = new LinkedList(1);
cout << h->getHeadValue() << endl;
system("pause");
return 0;
}
2、全局函数做友元
Friend Function和 friend 类一样,friend 函数可以拥有访问私有和受保护成员的权限。友元函数可以是:
a) 另一个类的成员
b) 全局函数
注意:
- 友元函数是 C++ 中的一个特殊函数,尽管它不是类的成员函数,但它具有访问类的私有和受保护数据的特权。
- 友元函数是类的非成员函数或普通函数,在类内部使用关键字friend声明为友元。通过将函数声明为友元,所有访问权限都授予该函数。
- 关键字“friend”只放在友元函数的函数声明中,不放在函数定义中。
- 当友元函数被调用时,既不使用对象的名称,也不使用点运算符。然而,它可以接受对象作为它想访问的值的参数。
- 友元函数可以在类的任何部分声明,即公共、私有或保护。
语法:
class <class_name>
{
friend <return_type> <function_name>(argument/s); //全局函数
};
例子
#include <iostream>
#include <algorithm>
using namespace std;
class Largest {
friend void shouMax(Largest l);
private:
int x, y, m;
public:
Largest():x(0), y(0), m(0) {}
Largest(int a, int b) : x(a), y(b), m(max(a, b)) {}
};
void shouMax(Largest l) {
cout << "Max value : " << l.m << endl;
}
int main() {
Largest l = Largest(1, 2);
shouMax(l);
return 0;
}
也可以在全局函数中定义多个类,并在这些类中声明全局函数为友元函数
#include <iostream>
#include <algorithm>
using namespace std;
class B; //前向定义
class A {
friend int findMax(A t1, B t2);
private:
int a;
public:
A(int x) : a(x) {}
};
class B {
friend int findMax(A t1, B t2);
private:
int b;
public:
B(int x): b(x) {}
};
int findMax(A t1, B t2) {
int m = max(t1.a, t2.b);
return m;
}
int main() {
cout << findMax(A(1), B(2)) << endl;
return 0;
}
class Node {
private:
int key;
Node* next;
/* Other members of Node Class */
friend int LinkedList::search();
// Only search() of linkedList
// can access internal members
};
以下是关于友元函数和类的一些要点:
-
友元只能用于有限的目的。太多的函数或外部类被声明为具有受保护或私有数据的
-
类的友元,这降低了面向对象编程中单独类封装的价值。
-
友元不是相互的。如果类 A 是 B 的朋友,那么 B 不会自动成为 A 的朋友。
-
友谊不是继承的
-
Java中没有友元的概念。
一个简单而完整的C++程序来展示朋友类
#include <iostream>
class A {
private:
int a;
public:
A() { a = 0; }
friend class B; // Friend Class
};
class B {
private:
int b;
public:
void showA(A& x)
{
// Since B is friend of A, it can access
// private members of A
std::cout << "A::a=" << x.a;
}
};
int main()
{
A a;
B b;
b.showA(a);
return 0;
}
3、成员函数做友元
#include <iostream>
#include <algorithm>
using namespace std;
class B; //前向定义
class A {
public:
void showB(B& b); //注意并不能再这里实现,因为虽然类在此前定义了但是并未实现
};
class B {
friend void A::showB(B& b); //将A中的shouB函数作为友元
private:
int val;
public:
B(int x): val(x) {}
};
void A::showB(B& b) {
cout << b.val << endl;
}
int main() {
A a;
B b = B(1);
a.showB(b);
return 0;
}
举个例子:
两个类Buliding和GoodFriend,Buliding中有public属性的livingroom,private属性的bedroom
让GoogFriend中的友元函数visitBedroom可以访问Building中的bedroom
#include <iostream>
#include <algorithm>
using namespace std;
class Building;
class GoodFriend {
private:
string name;
public:
Building *building; //注意这里是指针(如果传值会出错)
GoodFriend();
GoodFriend(string n);
void visitLivingroom(); //参观客厅(public)
void visitBedroom(); //参观卧室(private)
};
class Building {
friend void GoodFriend::visitBedroom(); //授予GoodFriend类访问私有成员的权限
private:
string bedroom;
public:
string livingroom;
Building() {
bedroom = "", livingroom = "";
}
Building(string be, string li) {
bedroom = be, livingroom = li;
}
};
GoodFriend::GoodFriend(){
name = "";
building =new Building(); //注意GoodFriend的构造函数需要写在类外实现,Buliding只是在之前进行了声明
}
GoodFriend::GoodFriend(string n){
name = n;
building = new Building("bedroom", "livingroom"); //同理
}
void GoodFriend::visitBedroom() {
cout << "Visting :" << building->bedroom << endl;
}
void GoodFriend::visitLivingroom() {
cout << "Visting :" << building->livingroom << endl;
}
int main() {
GoodFriend f = GoodFriend("leon");
f.visitBedroom();
f.visitLivingroom();
return 0;
}