友元
介绍
在C++中,友元(friend) 是一种特殊的访问控制机制,允许其他类或其他函数访问当前类的私有成员和保护成员。友元的主要目的是为了提供更灵活的访问权限,尤其是在需要多个类之间紧密合作的情况下。
友元类型
(1) 友元函数:一个普通的函数可以被声明为某个类的友元函数,这样它就可以访问该类的私有和保护成员。
class MyClass {
private:
int data;
public:
MyClass(int val) : data(val) {}
friend void showData(MyClass obj); // 声明友元函数
};
void showData(MyClass obj) {
std::cout << "Data: " << obj.data << std::endl; // 访问私有成员
}
(2) 友元类:一个类可以被声明为另一个类的友元类,这样友元类的所有成员函数都可以访问该类的私有和保护成员。
class MyClass {
private:
int data;
public:
MyClass(int val) : data(val) {}
friend class FriendClass; // 声明友元类
};
class FriendClass {
public:
void display(MyClass obj) {
std::cout << "Data: " << obj.data << std::endl; // 访问私有成员
}
};
(3) 友元成员函数:一个类的成员函数可以被声明为另一个类的友元,这样该成员函数可以访问另一个类的私有和保护成员。
class MyClass {
private:
int data;
public:
MyClass(int val) : data(val) {}
friend void FriendClass::display(MyClass obj); // 声明友元成员函数
};
class FriendClass {
public:
void display(MyClass obj) {
std::cout << "Data: " << obj.data << std::endl; // 访问私有成员
}
};
友元特点和应用场景
- 不继承:友元关系不是继承关系,友元类或函数并不自动成为其他类的友元。
- 不对称:如果类A是类B的友元,类B并不一定是类A的友元。
- 访问权限:友元可以访问私有和保护成员,但友元本身并不是类的成员。
- 设计考虑:使用友元可以提高类之间的协作,但过度使用可能会导致代码的封装性降低,因此应谨慎使用
操作符重载:在重载某些操作符时,可能需要访问类的私有成员。
用法
友元 作用
友元是针对类来说的,友元可以让其他类或其他函数访问当前类的私有成员和保护成员
友元平常并不推荐使用,只要可以用友元写出必须用友元的重载运算符就可以了
友元 注意事项
(1) 友元会破坏封装性一般不推荐使用,所带来的方便写几个接口函数就解决了
(2) 某些运算符的重载必须用到友元的功能,这才是友元的真正用途
友元 相关代码
友元基本使用
#include <iostream>
class Test
{
friend class Test2; // 声明Test2为友元类
friend void output(const Test& test); // 声明output函数为友元函数
public:
Test() = default;
~Test() = default;
private:
std::string name = "lisi";
int age = 100;
};
// 另一个类访问私有成员
class Test2
{
public:
Test2() {};
~Test2() {};
void output(const Test& test) const // 为了在Test2类里访问Test类的私有成员,在Test类里声明Test2为友元类
{
std::cout << "name = " << test.name << ", age = " << test.age << std::endl;
}
};
// 另一个函数访问私有成员
void output(const Test& test) // 为了在output函数里访问Test的私有成员,在Test类里声明output函数为友元函数
{
std::cout << "name = " << test.name << ", age = " << test.age << std::endl;
}
int main()
{
Test t1;
Test2 t2;
t2.output(t1);
output(t1);
return 0;
}
利用公共接口代替友元
#include <iostream>
class Test
{
public:
Test() = default;
~Test() = default;
// 要想其他的类或函数 访问私有成员,友元会破坏封装性
// 最好的方式是直接多写一些公共接口就行了,也可以达到一样的效果,而且不破坏封装性
std::string getName() const{ return name; }
int getAge() const { return age; }
private:
std::string name = "lisi";
int age = 100;
};
// 另一个类访问私有成员
class Test2
{
public:
Test2() {};
~Test2() {};
void output(const Test& test) const
{ // 使用公共接口访问
std::cout << "name = " << test.getName() << ", age = " << test.getAge() << std::endl;
}
};
// 另一个函数访问私有成员
void output(const Test& test)
{
// 使用公共接口访问
std::cout << "name = " << test.getName() << ", age = " << test.getAge() << std::endl;
}
int main()
{
Test t1;
Test2 t2;
t2.output(t1);
output(t1);
return 0;
}