🎩 欢迎来到技术探索的奇幻世界👨💻
📜 个人主页:@一伦明悦-CSDN博客
✍🏻 作者简介: C++软件开发、Python机器学习爱好者
🗣️ 互动与支持:💬评论 👍🏻点赞 📂收藏 👀关注+
如果文章有所帮助,欢迎留下您宝贵的评论,点赞加收藏支持我,点击关注,一起进步!
目录
引言
正文
01-友元简介
02-全局函数做友元
03-类做友元
04-成员函数做友元
总结
引言
在C++中,友元(friend)是一种权限控制机制,让一个类的非成员函数或其他类的成员函数能够访问该类的私有成员。友元函数和友元类可以访问类的私有和保护成员,但它们并不是类的成员。
友元(friend)是C++中的一个特殊机制,它允许一个函数或者类访问另一个类的私有成员。在面向对象编程中,类通常将成员变量和成员函数分为公有(public)、私有(private)和保护(protected)三种访问权限。公有成员可以被类的对象直接访问,而私有成员则只能被该类的成员函数访问,不能被外部函数或其他类访问。友元机制允许某些函数或类突破这种封装性,可以直接访问类的私有成员。
友元的主要用途包括但不限于:
(1)允许外部函数访问类的私有成员:有时候,可能需要一些函数能够直接访问类的私有成员以完成某些任务,这时可以将这些函数声明为类的友元函数。
(2)提供不同类之间的访问权限:有时候,可能需要两个类之间共享信息,但这些信息又不适合设置为公有成员,这时可以将一个类声明为另一个类的友元类。 友元机制的使用应该谨慎,因为它破坏了类的封装性,可能导致代码耦合性增加,降低代码的可维护性和可读性。
友元类的作用是让一个类的成员函数可以访问另一个类的私有成员。
正文
01-友元简介
生活中你的家有客厅(Public),有你的卧室(Private) 客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去 但是呢,你也可以允许你的好闺蜜好基友进去。
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的关键字为 ==friend==
友元的三种实现:全局函数做友元;类做友元;成员函数做友元
在C++中,友元可以是函数,也可以是类。友元函数和友元类可以访问类的私有成员,但它们并不是类的成员。友元函数有两种形式:非成员函数友元和友元类。
(1)非成员函数友元
下面是一个示例代码,其中定义了一个名为Student的类,同时定义了一个非成员函数printName(),并将其声明为Student类的友元函数,可以访问Student类的私有成员:
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
public:
Student(string n) : name(n) {}
friend void printName(Student s);
};
void printName(Student s) {
cout << "Student name: " << s.name << endl;
}
int main() {
Student stu("Alice");
printName(stu);
return 0;
}
(2)友元类
下面是一个示例代码,创建了两个类ClassA和ClassB,其中ClassA将ClassB声明为友元类,从而允许ClassB类的成员函数访问ClassA类的私有成员:
#include <iostream>
using namespace std;
class ClassA {
private:
int num;
public:
ClassA(int n) : num(n) {}
friend class ClassB;
};
class ClassB {
public:
void printNum(ClassA a) {
cout << "Number from ClassA: " << a.num << endl;
}
};
int main() {
ClassA objA(10);
ClassB objB;
objB.printNum(objA);
return 0;
}
注:友元函数和友元类虽然提供了更灵活的权限控制机制,但也破坏了类的封装性,可能导致代码耦合性增加。因此,在使用友元时应慎重考虑。
02-全局函数做友元
在C++中,全局函数作为友元是一种常见的使用情况,在这种情况下,全局函数被声明为某个类的友元函数,从而可以访问该类的私有成员,但并不是类的成员函数。全局函数作为友元可以方便地实现不属于类成员函数的功能,同时访问类的私有成员。
下面是一个示例代码,展示了如何使用全局函数作为友元:
在示例中,全局函数displayYear()
被声明为Car
类的友元函数,可以访问Car
类的私有成员brand
和year
。在main()
函数中,通过创建Car
对象myCar
并调用displayYear()
函数,实现了打印汽车品牌和年份的功能。通过友元函数,实现了访问私有成员的操作,而不需要将私有成员改为公有。
这种方式可以使得全局函数具有更强的灵活性,同时保持类的封装性,使程序更加模块化和可维护。但是在使用全局函数作为友元时也需要注意,友元函数的设计应该符合类的设计原则,避免滥用友元导致代码不可控制。
#include <iostream>
#include <string>
using namespace std;
class Car {
private:
string brand;
int year;
public:
Car(string b, int y) : brand(b), year(y) {}
friend void displayYear(Car c);
};
void displayYear(Car c) {
cout << "Car brand: " << c.brand << ", Year: " << c.year << endl;
}
int main() {
Car myCar("Toyota", 2021);
displayYear(myCar);
return 0;
}
下面给出具体代码分析全局函数做友元的具体应用过程,示例演示了如何在C++中使用全局函数作为友元函数,从而访问类的私有成员。代码具体解释:
a、首先,定义了一个名为Building
的类,其中有一个公有成员变量m_SittinRoom
和一个私有成员变量m_BedRoom
。
b、紧接着,在类的定义中使用了friend
关键字,将全局函数goodFriend
声明为Building
类的友元函数。这意味着goodFriend
函数可以访问Building
类的私有成员。
c、全局函数goodFriend
定义在类的外部,接受一个Building
对象的引用作为参数。
d、在goodFriend
函数中,通过参数building
访问了Building
类的公有成员变量m_SittinRoom
,并输出其值。然后尝试访问了Building
类的私有成员变量m_BedRoom
,同样输出其值。
e、test01
函数中创建了一个Building
对象building
,并调用了goodFriend
函数,将该对象传递给它。
f、在main
函数中调用了test01
函数,执行了示例的主要功能。
#include <iostream>
using namespace std;
#include <string>
class Building
{
friend void goodFriend(Building &building);
public:
Building()
{
m_SittinRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittinRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
// 如果传入的参数是引用类型传参,下方访问属性时不能使用指针方式->,使用.即可
void goodFriend(Building &building)
{
cout << "好朋友全局函数 正在访问: " << building.m_SittinRoom << endl;
// 私有属性无法访问 ,但是在类中加入friend void goodFriend(Building *building);这个声明,就可以访问
cout << "好朋友全局函数 正在访问: " << building.m_BedRoom << endl;
}
void test01()
{
Building building;
goodFriend(building);
}
int main()
{
test01();
system("pause");
return 0;
}
示例运行结果如下图所示:
03-类做友元
在C++中,除了全局函数可以作为友元外,类本身也可以作为另一个类的友元,这种情况下被称为类做友元。类做友元的主要作用是让一个类的成员函数可以访问另一个类的私有成员。通过设置友元关系,可以在一定程度上突破类的封装性,实现类之间的信息共享。
下面是一个示例代码,展示了一个类作为另一个类的友元的情形:
在示例中,MyClass
类中定义了私有成员变量myData
,并将FriendClass
类声明为友元类。FriendClass
类中的displayData
函数可以访问MyClass
类的私有成员变量myData
。在main
函数中,创建了MyClass
对象obj
和FriendClass
对象friendObj
,并调用friendObj
的displayData
函数传入MyClass
对象obj
来访问私有成员变量myData
。
通过类做友元,不同类之间可以相互访问私有成员,但需要注意友元关系可能导致耦合度增加,应该慎重使用以维护代码的封装性和可维护性。
#include <iostream>
#include <string>
using namespace std;
class FriendClass; // 提前声明FriendClass类
class MyClass {
private:
int myData;
public:
MyClass(int data) : myData(data) {}
friend class FriendClass; // 将FriendClass类声明为友元类
};
class FriendClass {
public:
void displayData(MyClass m) {
cout << "FriendClass is accessing private data: " << m.myData << endl;
}
};
int main() {
MyClass obj(100);
FriendClass friendObj;
friendObj.displayData(obj);
return 0;
}
下面给出具体代码分析类做友元的应用分析,这个示例演示了如何在C++中使用类做友元,即一个类允许另一个类访问自己的私有成员。代码具体解释如下:
a、首先,定义了两个类:Building
和goodGay
。
b、在Building
类中,使用friend
关键字声明了goodGay
类为友元类,这意味着goodGay
类可以访问Building
类的私有成员。
c、Building
类有两个成员变量,m_SittingRoom
和m_BedRoom
,分别表示客厅和卧室。其中,m_BedRoom
是私有成员,只能在类内部访问。
d、构造函数Building::Building()
初始化了客厅和卧室的成员变量。
e、goodGay
类有一个成员指针building
指向Building
类的对象,并在构造函数中为其动态分配了内存。
f、goodGay
类有一个公有成员函数visit()
,用于访问Building
类的私有成员。在该函数中,通过building
指针访问了Building
类的私有成员变量m_SittingRoom
和m_BedRoom
,并输出它们的值。
g、test01()
函数创建了一个goodGay
对象gg
,并调用了它的visit()
函数。
h、在main
函数中,调用了test01()
函数,执行了示例的主要功能。
总体来说,这个示例展示了如何通过类做友元的方式,在一个类中访问另一个类的私有成员,从而实现了信息的共享。
#include <iostream>
using namespace std;
#include <string>
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
friend class goodGay;
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
};
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void test01()
{
goodGay gg;
gg.visit();
}
int main() {
test01();
system("pause");
return 0;
}
示例运行结果如下图所示:
04-成员函数做友元
在C++中,除了全局函数和类可以作为友元外,类的成员函数也可以作为另一个类的友元函数,这种情况下被称为成员函数做友元。这种方式允许某个类的成员函数访问另一个类的私有成员。通过设置成员函数做友元,可以进一步细化访问权限,只允许某些特定的函数访问私有成员,而不是整个类。
下面是一个示例代码,展示了一个类的成员函数作为另一个类的友元函数的情形:
在上述示例中,MyClass
类中定义了一个成员函数friendFunction
,并将FriendClass
类的成员函数声明为它的友元函数。FriendClass
类中的displayData
函数可以访问MyClass
类的私有成员变量myData
,而MyClass
类中的friendFunction
函数可以访问FriendClass
类的私有成员变量secretData
。
在main
函数中,创建了MyClass
对象obj
和FriendClass
对象friendObj
,并调用了它们各自的友元函数,实现了跨类的私有成员访问。
#include <iostream>
#include <string>
using namespace std;
class FriendClass; // 提前声明FriendClass类
class MyClass {
private:
int myData;
public:
MyClass(int data) : myData(data) {}
// 将FriendClass的成员函数声明为友元函数
void friendFunction(FriendClass fc);
};
class FriendClass {
private:
string secretData;
public:
FriendClass(string data) : secretData(data) {}
// 成员函数做友元,可以访问MyClass的私有成员
void displayData(MyClass m) {
cout << "FriendClass is accessing private data: " << m.myData << endl;
cout << "FriendClass is accessing secret data: " << secretData << endl;
}
};
// 在MyClass中定义成员函数friendFunction,该函数可以访问FriendClass的私有成员
void MyClass::friendFunction(FriendClass fc) {
cout << "MyClass's friend function is accessing FriendClass's secret data: " << fc.secretData << endl;
}
int main() {
MyClass obj(100);
FriendClass friendObj("I am secret data");
friendObj.displayData(obj); // FriendClass的成员函数访问MyClass的私有成员
obj.friendFunction(friendObj); // MyClass的成员函数访问FriendClass的私有成员
return 0;
}
下面给出具体代码分析成员函数做友元的应用过程,这个示例演示了如何在C++中使用成员函数做友元,即一个类的成员函数允许另一个类访问自己的私有成员。下面是代码的具体解释:
a、首先,定义了两个类:Building
和goodGay
。
b、在Building
类中,使用friend
关键字声明了goodGay
类的成员函数visit()
为友元函数,这意味着visit()
函数可以访问Building
类的私有成员。
c、Building
类有两个成员变量,m_SittingRoom
和m_BedRoom
,分别表示客厅和卧室。其中,m_BedRoom
是私有成员,只能在类内部访问。
d、构造函数Building::Building()
初始化了客厅和卧室的成员变量。
e、goodGay
类有一个成员指针building
指向Building
类的对象,并在构造函数中为其动态分配了内存。
f、goodGay
类有两个公有成员函数visit()
和visit2()
,其中visit()
函数是另一个类Building
的友元函数,可以访问Building
类的私有成员;而visit2()
函数则无法访问Building
类的私有成员。
g、test01()
函数创建了一个goodGay
对象gg
,并调用了它的visit()
函数,从而访问了Building
类的私有成员。
h、在main
函数中,调用了test01()
函数,执行了示例的主要功能。
#include <iostream>
using namespace std;
#include <string>
class Building;
class goodGay
{
public:
goodGay();
void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
void visit2();
private:
Building *building;
};
class Building
{
//告诉编译器 goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容
friend void goodGay::visit();
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
};
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void goodGay::visit2()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
//cout << "好基友正在访问" << building‐>m_BedRoom << endl;
}
void test01()
{
goodGay gg;
gg.visit();
}
int main() {
test01();
system("pause");
return 0;
}
示例运行结果如下图所示:
总结
综上所述:友元是C++中的一种机制,允许某些特定的函数或类访问另一个类中的私有成员。这种机制破坏了封装性,但在某些情况下是非常有用的。以下是关于友元的一些总结:
友元函数:友元函数是一个不属于当前类的普通函数,但被允许访问类的私有成员。友元函数的声明应该在类的内部,通常在类的开头或结尾,使用 friend
关键字。友元函数的定义在类外部,但需要在函数名前加上类名以指明它是哪个类的友元函数。
(1)友元类:
a、友元类是一个类,被允许访问另一个类中的私有成员。
b、声明一个友元类时,在类的声明中使用 friend
关键字,使得该类可以访问当前类的私有成员。
c、友元关系不具有传递性,即如果 A 类是 B 类的友元,B 类不一定是 A 类的友元。
(2)成员函数做友元:
a、除了全局函数和类可以作为友元外,类的成员函数也可以作为另一个类的友元函数。
b、成员函数做友元的方式可以进一步细化访问权限,只允许某些特定的函数访问私有成员,而不是整个类。
(3)友元的使用场景:
a、当某些操作需要访问另一个类的私有成员时,可以使用友元机制。
b、在一些特定的设计模式中,友元机制也可以用于实现更灵活的访问控制。
(4)友元的注意事项:
a、友元破坏了类的封装性,增加了类之间的耦合性,因此应该谨慎使用。
b、友元应该被合理地使用,仅在确实需要访问私有成员时才使用,避免滥用。
c、友元关系应该尽可能地限制在必要的范围内,以保证代码的安全性和可维护性。
通过友元机制,可以在一定程度上打破类的封装性,但需要在设计时慎重考虑,确保代码的可维护性和安全性。