内容提要
-
面向对象
- 友元
友元
生活中的你家有客厅(public),有卧室(private)
客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你自己可以进入。
但是呢,你也可以允许客人中你的朋友进去。
在程序里,有些私有成员,也想让类外特殊的一些函数或者类进行访问,就需要用到友元
友元的目的是让一个函数或者类访问另一个类中的私有成员。
友元的关键字为friend
友元的三种实现:
①全局函数做友元
②类做友元
③成员函数做友元
全局函数做友元
/*************************************************************************
> File Name: demo01.cpp
> Author: 柯柯大王
> Description: 友元:全局函数做友元
> Created Time: 2025-08-21 08:52:42
************************************************************************/
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//创建Building类
class Building
{
//告诉编译器 goodFriend全局函数 是Building类的好朋友,可以访问类中的私有成员
friend void goodFriend(Building* building); //friend 函数
public:
//无参构造,此时会覆盖掉默认的无参
Building()
{
//赋值
this->sittingRoom = "客厅";
this->bedRoom = "卧室";
}
public:
string sittingRoom; //客厅 公共成员
private:
string bedRoom; //卧室 私有成员
};
//准备一个全局函数,用来做友元,实现对类中私有成员 bedRoom的访问
void goodFriend(Building* building)
{
cout << "好朋友正在造访:" << building->sittingRoom << endl; //客厅,正常访问
cout << "好朋友正在造访:" << building->bedRoom << endl; //卧室,需要借助友元访问
}
int main(int argc, char **argv)
{
Building b;
goodFriend(&b);
system("pause");
return 0;
}
类做友元
/*************************************************************************
> File Name: demo02.cpp
> Author: 柯柯大王
> Description: 友元:类做友元
> Created Time: 2025-08-21 09:58:18
************************************************************************/
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//创建类BUilding
class Building
{
//告诉编译器 GoodFriend类是Building类的好朋友,可以访问到Building类中的私有成员
friend class GoodFriend;
public:
Building();
string sittingRoom; //客厅 公共成员
private:
string bedRoom; //卧室 私有成员
};
//定义Building类的构造函数
Building::Building()
{
this->sittingRoom = "客厅";
this->bedRoom = "卧室";
}
//创建类GoodFriend
class GoodFriend
{
public:
GoodFriend()
{
this->building = new Building(); //此时就不在栈区,在 自由存储区,大概率在堆区
}
//访问好朋友(友元)Building的私有成员
void visit()
{
cout << "好朋友正在造访:" << building->sittingRoom << endl; //客厅,正常访问
cout << "好朋友正在造访:" << building->bedRoom << endl; //卧室
}
private:
Building *building;
};
//void GoodFriend::visit()
//{
// cout << "好朋友正在造访:" << building->sittingRoom << endl; //客厅,正常访问
// cout << "好朋友正在造访:" << building->bedRoom << endl; //卧室
//}
int main(int argc, char **argv)
{
GoodFriend gf;
gf.visit();
system("pause");
return 0;
}
成员函数做友元
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
// 类的声明,主要是解决类的嵌套
class Building;
// 类的定义
// 创建友元类
class GoodFriend
{
public:
GoodFriend();
void visit();
private:
Building *building;
};
// 创建Building类
class Building
{
// 告诉编译器 GoodFrind类中某个函数(visit)作为Building类的好朋友,可以
访问Building中的私有成员
friend void GoodFriend::visit();
public:
// 无参构造函数
Building()
{
// 初始化(所谓初始化,就是给类对象的成员变量赋初值)
this->sittingRoom = "客厅";
this->bedRoom = "卧室";
}
public:
string sittingRoom; // 客厅 公共成员
private:
string bedRoom; // 卧室 私有成员
};
GoodFriend::GoodFriend()
{
this->building = new Building();
}
void GoodFriend::visit()
{
cout << "好朋友正在造访:" << building->sittingRoom << endl; // 客
厅,正常访问
cout << "好朋友正在造访:" << building->bedRoom << endl; // 卧
室,需要借助友元访问
}
int main(int argc, char **argv)
{
GoodFriend gf;
gf.visit();
system("pause");
return 0;
}
如果涉及到类的嵌套访问,比如成员函数做友元的时候。我们建议将成员函数定义到类的外部,同时需要给类加上类声明。
运算符重载【了解】
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以使用不同的数据类型。
加号运算符
**作用:**实现两个自定义数据类型相加的运算
示例:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Person
{
public:
Person(){}
Person(int a, int b)
{
this->a = a;
this->b = b;
}
// 成员函数实现 + 号运算符重载
Person operator+(const Person& p)
{
Person temp;
temp.a = this->a + p.a;
temp.b = this->b + p.b;
return temp;
}
public:
int a;
int b;
};
// 全局函数实现 + 号运算符重载
Person operator+(const Person& p1, const Person& p2)
{
Person temp;
temp.a =p1.a + p2.a;
temp.b =p1.b + p2.b;
return temp;
}
// 运算符重载 可以发生函数重载
Person operator+(const Person& p2, int val)
{
Person temp;
temp.a =p2.a + val;
temp.b =p2.b + val;
return temp;
}
int main(int argc, char **argv)
{
Person p1(10,20);
Person p2(20,20);
// 测试成员函数方式
Person p3 = p2 + p1; // 相当于 p3 = p2.operator+(p1)
cout << "a = " << p3.a << ",b = " << p3.b << endl;
Person p4 = p3 + 10; // 相当于 p4 = operator+(p3, 10)
cout << "a = " << p4.a << ",b = " << p4.b << endl;
system("pause");
return 0;
}
总结1:对于内置的数据类型的表达式的运算符是不可能改变的
总结2:不要滥用运算符重载