作者:jicanmeng
时间:2014年11月30日
通常,类的私有成员和保护成员只能由类的成员函数来访问,类的对象和外部函数只能访问类的public成员。但是我们有时会有这样的需求:直接在类的某个外部函数funcA()中访问类的私有数据。如果我们在类中定义一个public类型的成员函数,那么funcA()就可以调用这个成员函数访问类的私有数据了,但同时别的外部函数如funcB()也能调用这个类的成员函数。我们的要求是只有funcA()能访问类的私有数据,别的函数则不可以。这种情况下,我们可以将funcA()函数声明为这个类的友元函数(friend function)。
一个类的友元函数在这个类中进行声明,前面需要添加C++关键字"friend"。从字面意义来看,一个类的友元函数就是这个类的朋友,可以访问类的public、protected和private类型的成员。
learncpp.com上面是这样描述的:
A friend function is a function that can access the private members of a class as though it were a member of that class. In all other regards, the friend function is just like a normal function. A friend function may or may not be a member of another class. To declare a friend function, simply use the friend keyword in front of the prototype of the function you wish to be a friend of the class. It does not matter whether you declare the friend function in the private or public section of the class.
看一个示例程序:
#include <iostream>
class Value
{
private:
int m_nValue;
public:
Value(int nValue) { m_nValue = nValue; }
friend bool IsEqual(const Value &cValue1, const Value &cValue2);
};
bool IsEqual(const Value &cValue1, const Value &cValue2)
{
return (cValue1.m_nValue == cValue2.m_nValue);
}
int main()
{
Value cValue1(1);
Value cValue2(2);
std::cout << (IsEqual(cValue1, cValue2)?"equal":"not equal") << std::endl;
return 0;
}
几点说明:
一个函数可以同时是多个类的友元函数。如下面的程序:
#include <iostream>
class Humidity;
class Temperature
{
private:
int m_nTemp;
public:
Temperature(int nTemp) { m_nTemp = nTemp; }
friend void PrintWeather(Temperature &cTemperature, Humidity &cHumidity);
};
class Humidity
{
private:
int m_nHumidity;
public:
Humidity(int nHumidity) { m_nHumidity = nHumidity; }
friend void PrintWeather(Temperature &cTemperature, Humidity &cHumidity);
};
void PrintWeather(Temperature &cTemperature, Humidity &cHumidity)
{
std::cout << "The temperature is " << cTemperature.m_nTemp <<
" and the humidity is " << cHumidity.m_nHumidity << std::endl;
}
int main()
{
Temperature cTemperature(25);
Humidity cHumidity(30);
PrintWeather(cTemperature, cHumidity);
return 0;
}
一个类的友元函数可以是其它类的成员函数。将上面的程序修改一下:
#include <iostream>
class Humidity;
class Temperature
{
private:
int m_nTemp;
public:
Temperature(int nTemp) { m_nTemp = nTemp; }
void PrintWeather(Humidity &cHumidity);
};
class Humidity
{
private:
int m_nHumidity;
public:
Humidity(int nHumidity) { m_nHumidity = nHumidity; }
friend void Temperature::PrintWeather(Humidity &cHumidity);
};
void Temperature::PrintWeather(Humidity &cHumidity)
{
std::cout << "The temperature is " << m_nTemp <<
" and the humidity is " << cHumidity.m_nHumidity << std::endl;
}
int main()
{
Temperature cTemperature(25);
Humidity cHumidity(30);
cTemperature.PrintWeather(cHumidity);
return 0;
}
更进一步,我们可以将一个类声明为另外一个类的友元类。假设类ClassA为ClassB的友元类,那么ClassA中的所有成员函数都是ClassB的友元函数(这句话的意思是,ClassA的所有成员函数的参数中如果有Class &类型的变量,那么该成员函数就是ClassB的友元函数。)
示例程序如下:
#include <iostream>
class Storage
{
private:
int m_nValue;
double m_dValue;
public:
Storage(int nValue, double dValue)
{
m_nValue = nValue;
m_dValue = dValue;
}
// Make the Display class a friend of Storage
friend class Display;
};
class Display
{
private:
bool m_bDisplayIntFirst;
public:
Display(bool bDisplayIntFirst) { m_bDisplayIntFirst = bDisplayIntFirst; }
void DisplayItem(Storage &cStorage)
{
if (m_bDisplayIntFirst)
std::cout << cStorage.m_nValue << " " << cStorage.m_dValue << std::endl;
else // display double first
std::cout << cStorage.m_dValue << " " << cStorage.m_nValue << std::endl;
}
};
int main()
{
Storage cStorage(5, 6.7);
Display cDisplay(false);
cDisplay.DisplayItem(cStorage);
return 0;
}