For much of this
来源:互联网 发布:进出口报关软件 编辑:程序博客网 时间:2024/06/06 12:26
For much of this chapter, we’ve been preaching the virtues of keeping your data private. However, you may occasionally find situations where you will find you have classes and functions that need to work very closely together. For example, you might have a class that stores data, and a function (or another class) that displays the data on the screen. Although the storage class and display code have been separated for easier maintenance, the display code is really intimately tied to the details of the storage class. Consequently, there isn’t much to gain by hiding the storage classes details from the display code.
In situations like this, there are two options:
1) Have the display code use the publicly exposed functions of the storage class. However, this has several potential downsides. First, these public member functions have to be defined, which takes time, and can clutter up the interface of the storage class. Second, the storage class may have to expose functions for the display code that it doesn’t really want accessible to anybody else. There is no way to say “this function is meant to be used by the display class only”.
2) Alternatively, using friend classes and friend functions, you can give your display code access to the private details of the storage class. This lets the display code directly access all the private members and functions of the storage class! In this lesson, we’ll take a closer look at how this is done.
Friend functions
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 thefriend 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.
Here’s an example of using a friend function:
class
Accumulator
{
private
:
int
m_nValue;
public
:
Accumulator() { m_nValue = 0; }
void
Add(
int
nValue) { m_nValue += nValue; }
// Make the Reset() function a friend of this class
friend
void
Reset(Accumulator &cAccumulator);
};
// Reset() is now a friend of the Accumulator class
void
Reset(Accumulator &cAccumulator)
{
// And can access the private data of Accumulator objects
cAccumulator.m_nValue = 0;
}
In this example, we’ve declared a function named Reset() that takes an object of class Accumulator, and sets the value of m_nValue to 0. Because Reset() is not a member of the Accumulator class, normally Reset() would not be able to access the private members of Accumulator. However, because Accumulator has specifically declared this Reset() function to be a friend of the class, the Reset() function is given access to the private members of Accumulator.
Note that we have to pass an Accumulator object to Reset(). This is because Reset() is not a member function. It does not have a *this pointer, nor does it have an Accumulator object to work with, unless given one.
While this example is pretty contrived, here’s another example that’s a lot closer to something you’ll see again in the near future, when we talk about operator overloading:
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);
}
In this example, we declare the IsEqual() function to be a friend of the Value class. IsEqual() takes two Value objects as parameters. Because IsEqual() is a friend of the Value class, it can access the private members of all Value objects. In this case, it uses that access to do a comparison on the two objects, and returns true if they are equal.
A function can be a friend of more than one class at the same time. For example, consider the following example:
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;
}
There are two things worth noting about this example. First, because PrintWeather is a friend of both classes, it can access the private data from objects of both classes. Second, note the following line at the top of the example:
class
Humidity;
This is a class prototype that tells the compiler that we are going to define a class called Humidity in the future. Without this line, the compiler would tell us it doesn’t know what a Humidity is when parsing the prototype for PrintWeather() inside the Temperature class. Class prototypes serve the same role as function prototypes — they tell the compiler what something looks like so it can be used now and defined later. However, unlike functions, classes have no return types or parameters, so class prototypes are always simply class ClassName
, where ClassName is the name of the class.
Friend classes
It is also possible to make an entire class a friend of another class. This gives all of the members of the friend class access to the private members of the other class. Here is an example:
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;
}
};
Because the Display class is a friend of Storage, any of Display’s members that use a Storage class object can access the private members of Storage directly. Here’s a simple program that shows the above classes in use:
int
main()
{
Storage cStorage(5, 6.7);
Display cDisplay(
false
);
cDisplay.DisplayItem(cStorage);
return
0;
}
This program produces the following result:
A few additional notes on friend classes. First, even though Display is a friend of Storage, Display has no direct access to the *this pointer of Storage objects. Second, just because Display is a friend of Storage, that does not mean Storage is also a friend of Display. If you want two classes to be friends of each other, both must declare the other as a friend. Finally, if class A is a friend of B, and B is a friend of C, that does not mean A is a friend of C.
Be careful when using friend functions and classes, because it allows the friend function or class to violate encapsulation. If the details of the class change, the details of the friend will also be forced to change. Consequently, limit your use of friend functions and classes to a minimum.
- For much of this
- Joomla extensions coding Search for somebody with much experience of Joomla. $10000
- hi, do you see this new? hoho~~~i will start...thank you so much for you help!~~^~^~~
- E文积累_20071208_not much of
- 解决 “serial8250: too much work for irq4”
- WOW makes much money for blizzard
- too much data for RSA block
- Cannot find utCompiledCode record for this version of the uninstaller
- error: L6050U: The code size of this image exceeds the maximum allowed for this versio
- The developers of this app have not set up this app properly for Facebook Login?
- How much of Silverlight is in Windows Phone 7
- It doesn't take much of you time
- The size of this image (170286 bytes) exceeds the maximum allowed for this version of the linker
- error: L6047U: The size of this image (32868 bytes) exceeds the maximum allowed for this version of
- How much time is needed ? ( Sample Study Plan for CSQA )
- mongodb too much data for sort() with no index
- Believe-I wait for you in a corner of this world
- Adding a required attribute while having CIs of this type for VCM version earlier than 7.6
- js比较不错的107条语句
- 数位dp BZOJ 2757: [SCOI2012]Blinker的仰慕者
- Protocol Buffer介绍
- rubyonrails 进行link_to语言添加style的语言和class的样式
- android 开源组件合集-UI篇(2013-11-07更新)
- For much of this
- 常见测试用例列表.docx
- js正则表达式
- OCP 1Z0 053 135
- When working with arrays
- 几道有意思的java编程题目
- hdu1029Ignatius and the Princess IV
- flexigrid 绑定事件process以及对行列的操作
- POj 1017-Packets