friend函数和friend类
友元机制允许一个类将对其非公有成员的访问权授予指定的函数或者类;友元的声明关键字是friend开始,它只出现在类定义的内部;友元声明可以出现在类中的任何位置:友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。
friend函数
在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。
将全局函数声明为友元:
friend 返回值类型 函数名(参数表);
将其他类的成员函数声明为友元(不能将其他类的私有成员函数声明为友元):
friend 返回值类型 其他类的类名::成员函数名(参数表);
#include <iostream>
using namespace std;
class Rectangle;
class Square
{
private:
int side;
public:
Square(int a) : side(a) {}
void SetSide(const class Rectangle& angle);
};
class Rectangle
{
private:
int m_nWidth;
int m_nHeight;
friend void Square::SetSide(const Rectangle& rect);
friend Rectangle duplicate(const Rectangle&); // friend functions
public:
Rectangle() {}
Rectangle(int nX, int nY) : m_nWidth(nX), m_nHeight(nY) {}
int area() { return m_nWidth * m_nHeight; }
};
void Square::SetSide(const class Rectangle& rect)
{
side = rect.m_nWidth;
}
Rectangle duplicate(const Rectangle& param)
{
Rectangle res;
//由于是类的firend函数,可以访问私有成员变量
res.m_nWidth = param.m_nWidth * 2;
res.m_nHeight = param.m_nHeight * 2;
return res;
}
friend函数并不是类的成员函数,所以并不受类的声明部分的访问控制影响。
friend类
友元类的声明在该类的声明中,而实现在该类外。
friend class <友元类名>;
#include <iostream>
using namespace std;
class Square
{
friend class Rectangle; // friend class
private:
int side;
public:
Square(int a) : side(a) {}
};
class Rectangle
{
private:
int m_nWidth;
int m_nHeight;
public:
Rectangle() {}
Rectangle(int nX, int nY) : m_nWidth(nX), m_nHeight(nY) {}
int area() { return m_nWidth * m_nHeight; }
void convert(Square a);
};
//由于Rectangle是Square的友元类,所以可以访问Square的私有成员变量
void Rectangle::convert(Square a)
{
m_nWidth = a.side;
m_nHeight = a.side;
}
friend的声明和作用域
在上述的使其他类的成员函数变成友元时,必须在使用之前先定义这个方法;否则Rectangle类不能将SetSide设置为友元;
然后只有再定义Rectangle类之后,才能定义SetSide的方法,毕竟设为友元的目的就是为了访问Rectangle类的成员(注意SetSide和上文中的位置,一个在Rectangle定义之前,一个在Rectangle定义之后):
#include <iostream>
using namespace std;
class Rectangle;
class Square
{
private:
int side;
public:
Square(int a) : side(a) {}
void SetSide(const class Rectangle& angle);
};
//error,此时Rectangle类还没有定义
void Square::SetSide(const class Rectangle& rect)
{
side = rect.m_nWidth;
}
class Rectangle
{
private:
int m_nWidth;
int m_nHeight;
friend void Square::SetSide(const Rectangle& rect);
friend Rectangle duplicate(const Rectangle&); // friend functions
public:
Rectangle() {}
Rectangle(int nX, int nY) : m_nWidth(nX), m_nHeight(nY) {}
int area() { return m_nWidth * m_nHeight; }
};
Rectangle duplicate(const Rectangle& param)
{
Rectangle res;
//由于是类的firend函数,可以访问私有成员变量
res.m_nWidth = param.m_nWidth * 2;
res.m_nHeight = param.m_nHeight * 2;
return res;
}
友元引入的类名和函数,可以像预先声明的一样使用:
注意上文中friend函数的代码段和friend的代码段区别:
class Rectangle;//在第一段代码中定义Square之前我们预先声明了class rectangle;
friend class Rectangle;//在第二段代码中我们并没有在定义Square之前预先声明Rectangle类,而是利用了友元的声明。