C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。
1.友元的内容
友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。
2.非成员友元函数
友元函数是在类中用关键字friend修饰的非成员函数,可以是一个普通的函数,或是其它类的成员函数。
虽然它不是本类的成员函数,却在它的函数体中却可以通过对象名访问类的私有成员和保护成员。
#include <iostream>
using namespace std;
void showAge(); //声明
class ClassA
{
public:
ClassA(int x,int y)
{
m_x = x;
m_y = y;
}
void printXY()
{
//cout<<"("<<this->m_x<<","<<this->m_y<<")"<<endl;
cout<<"("<<m_x<<","<<m_y<<")"<<endl;
}
friend int add(ClassA &a); //友元函数可以在这里直接定义,也可以在类外定义,但是必须在类内部声明
friend void setAge(int age);
friend void showAge()//在类内部定义,需要在外部进行声明,否则main函数找不到
{
cout<<"age:"<< m_age <<endl;//类内部定义可以用m_age,外部定义要用ClassA::m_age
//cout<<"age:"<< ClassA::m_age <<endl;
}
private:
int m_x,m_y;
static int m_age;
};
int ClassA::m_age = 0;//定义+初始化,C++静态成员变量必须定义,否则没有申请内存
int add(ClassA &a)
{
return a.m_x + a.m_y;
}
void setAge(int age)
{
//m_age = age; //问题2:使用m_age报错,需使用ClassA::m_age
ClassA::m_age = age;
}
int main(void)
{
int sum = 0;
ClassA a(3,5);
a.printXY();
sum = add(a);
cout<<"sum:"<<sum<<"\n";
showAge();
setAge(30);
showAge();
return 0;
}
普通的非成员函数友元使用:
- 友元函数在类外声明,类内定义,定义加friend;
- 友元函数在类内声明,类外定义,声明加friend;
- 友元函数访问普通成员变量需要基于某个实例对象,访问static静态成员变量可以直接访问;
友元函数和类的成员函数的区别:
- 成员函数有this指针,而友元函数没有this指针。
3.成员友元函数
这个稍微有点复杂,因为你要类成员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。(如果是友元类,则没有这种这种必须)如下面所示:
https://blog.csdn.net/ddupd/article/details/38053159
4.类作为友元
同友元函数一样,一个类可以将另一个类声明为友元类。若A类为B类的友元函类,则A类中的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。例如:
#include <iostream>
using namespace std;
class ClassA
{
friend class ClassB;
public:
ClassA()
{
}
void printX()
{
cout<<"m_x:"<<m_x<<",m_age"<<m_age<<endl;
}
private:
int m_x=0;
static int m_age;
};
int ClassA::m_age=1;
class ClassB
{
public:
void set(int x);
//private:
ClassA m_A;
};
void ClassB::set(int x)
{
m_A.m_x = x;//由于B类是A类的友元类,所以在B的成员函数中可以访问A类对象的私有成员
ClassA::m_age = x;
}
int main(void)
{
ClassB b;
b.m_A.printX();
b.set(10);
b.m_A.printX();
return 0;
}
5.友元注意事项
1.友元不具有相互性/友元关系是单向的:
只具有单项性 若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
2.友元不能被继承:
B是A的友元类,C是B的子类,推不出C是A的友元
3.友元不具有传递性:
B是A的友元,C是B的友元,推不出C是A的友元
参考资料:
https://blog.csdn.net/ddupd/article/details/38053159
https://blog.csdn.net/yiwanyuan2756/article/details/80437536
http://www.cnblogs.com/CBDoctor/archive/2012/02/04/2337733.html