目录
推荐:c++成员运算符重载和友元运算符重载的比较(以++,--运算符为例)https://blog.csdn.net/ayangya/article/details/78901294
友元(friend)
C++中友元(友元函数和友元类)的用法和功能:https://blog.csdn.net/adriano119/article/details/5914443
C++友元函数和友元类用法详解:https://blog.csdn.net/fanyun_01/article/details/79122916
类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。
但是,有时候需要在类的外部访问类的私有成员
解决方法是使用友元函数,友元函数是一种特权函数,C++允许这个特权函数访问私有成员。
使用友元要务必注意,因为会破坏类的数据隐藏
全局函数做友元函数
- 在类外声明函数原型(因为是全局函数) 【 返回值 函数名 (形式参数); 】
- 在类内加上friend关键字,再次声明函数原型【 friend 返回值 函数名 (形式参数); 】
- 在cpp中进行函数定义,友元函数可以访问类的私有变量
class Time : public QMainWindow
{
public:
Time();
~Time();
int min;
private:
int second;
};
void Frifunction(Time * time);
Time::Time():
min(10),
second(20)
{
qDebug()<<"进入Time构造函数";
}
Time::~Time()
{
qDebug()<<"进入Time析构函数";
}
void Frifunction(Time * time)
{
qDebug()<<time->min<<time->second;
}
没有声明友元的情况下,编译器报错
second是私有成员变量,只要成员函数可以访问,如果全局函数想访问,需要在类中,加friend关键字,并且再次声明
class Time : public QMainWindow
{
public:
Time();
~Time();
int min;
friend void Frifunction(Time * time);//2,在类内加上friend关键字,再次声明函数原型
private:
int second;
};
void Frifunction(Time * time);//1,在类外声明函数原型(因为是全局函数)
Time::Time():
min(10),
second(20)
{
qDebug()<<"进入Time构造函数";
}
Time::~Time()
{
qDebug()<<"进入Time析构函数";
}
void Frifunction(Time * time)
{
qDebug()<<time->min<<time->second;
}
此时程序就不会报错了
需要在类中增加一句:friend 返回值 函数名(形式参数);
Time t;
Frifunction(&t);
因为在默认构造函数中已经初始化,程序输出如下:
友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
友元函数的调用与一般函数的调用方式和原理一致。
类做友元
- A类想要访问B类中的所有成员变量
- 在B类中声明:【friend class A】
在想被访问的类中添加friend声明
.h
class PinkFloyd
{
public:
PinkFloyd();
~PinkFloyd();
int music;
void JustTest();
private:
int Rock;
};
class Time
{
public:
Time();
~Time();
int min;
private:
int sec;
};
.cpp
PinkFloyd::PinkFloyd():
music(1968),
Rock(2020)
{
qDebug()<<"进入PinkFloyd构造函数";
}
PinkFloyd::~PinkFloyd()
{
qDebug()<<"进入PinkFloyd析构函数";
}
void PinkFloyd::JustTest()
{
qDebug()<<"进入JustTest";
Time T;
qDebug()<<"T.sec"<<T.sec;
}
Time::Time():
min(20),
sec(20)
{
qDebug()<<"进入Time构造函数";
}
Time::~Time()
{
qDebug()<<"进入Time构造函数";
}
程序会报错:
目前是PinkFloyd所在的类想要访问Time中的私有变量,所有,在Time中增加一句声明
class Time
{
public:
Time();
~Time();
friend class PinkFloyd;//友元类的声明
int min;
private:
int sec;
};
成员函数做友元
- A类成员函数想访问B类私有变量
- 在B类中声明:【friend 返回值 所在类名::函数名 (形式参数)】
.h
class PinkFloyd
{
public:
PinkFloyd();
~PinkFloyd();
int music;
void JustTest();
void OnlyTest();//只让onlytest函数能访问Time中的成员变量
private:
int Rock;
};
class Time
{
public:
Time();
~Time();
int min;
friend void PinkFloyd::OnlyTest();//成员函数做友元函数
private:
int sec;
};
.cpp
void PinkFloyd::OnlyTest()
{
qDebug()<<"进入OnlyTest";
Time T;
qDebug()<<"T.sec"<<T.sec;
}
总结
使用友元类时注意:
- 友元关系不能被继承。
- 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
- 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的
同样,友元函数没有this指针。