1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
To grant nested classes access rights to the private members of their
surrounding class, to grant access to the private members of other nested
classes, or to grant a surrounding class access to the private members of its
nested classes the hi(friend: nested classes)tt(friend) keyword must be used.
Consider the following situation where a class tt(Surround) has two nested
classes tt(FirstWithin) and tt(SecondWithin). Each of the three classes has a
static data member tt(int s_variable):
verb(
class Surround
{
static int s_variable;
public:
class FirstWithin
{
static int s_variable;
public:
int value();
};
int value();
private:
class SecondWithin
{
static int s_variable;
public:
int value();
};
};
)
If the class tt(Surround) should be able to access tt(FirstWithin) and
tt(SecondWithin)'s private members, these latter two classes must declare
tt(Surround) to be their friend. The function tt(Surround::value) can
thereupon access the private members of its nested classes. For example (note
the tt(friend) declarations in the two nested classes):
verb(
class Surround
{
static int s_variable;
public:
class FirstWithin
{
friend class Surround;
static int s_variable;
public:
int value();
};
int value();
private:
class SecondWithin
{
friend class Surround;
static int s_variable;
public:
int value();
};
};
inline int Surround::FirstWithin::value()
{
FirstWithin::s_variable = SecondWithin::s_variable;
return (s_variable);
}
)
To allow the nested classes access to the private members of their
surrounding class, the class tt(Surround) must declare its nested classes as
friends. As the tt(friend) keyword may only be used when the class that is to
become a friend is already known as a class by the compiler, either a
i(forward declaration) of the nested classes is required (to be followed by
the friend declaration), or the friend declaration follows the definition of
the nested classes. The forward declaration followed by the friend declaration
looks like this:
verb(
class Surround
{
public:
class FirstWithin;
class SecondWithin;
friend class FirstWithin;
friend class SecondWithin;
class FirstWithin
{ ... };
...
};
)
Alternatively, the friend declaration may follow the definition of the
classes. A class can be declared a friend following its definition, with
in-class code already using the fact that it will be declared a friend of the
outer class. Furthermore, in-class defined nested class members may already
use members of the surrounding class that have not yet been seen by the
compiler. Finally note that `tt(s_variable)' which is
hi(nested class: member access) defined in the class tt(Surround) may be
accessed by the nested classes as tt(Surround::s_variable):
verb(
class Surround
{
static int s_variable;
public:
class FirstWithin
{
friend class Surround;
static int s_variable;
public:
int value();
};
friend class FirstWithin;
int value();
private:
class SecondWithin
{
friend class Surround;
static int s_variable;
public:
int value();
};
static void classMember();
friend class SecondWithin;
};
inline int Surround::value()
{
FirstWithin::s_variable = SecondWithin::s_variable;
return s_variable;
}
inline int Surround::FirstWithin::value()
{
Surround::s_variable = 4;
Surround::classMember();
return s_variable;
}
inline int Surround::SecondWithin::value()
{
Surround::s_variable = 40;
return s_variable;
}
)
Finally, tt(friend) declarations must be applied to grant the nested
classes access to each other's private members. To grant tt(FirstWithin)
access to tt(SecondWithin)'s private members nothing but a tt(friend)
declaration in tt(SecondWithin) is required. However, to grant
tt(SecondWithin) access to tt(FirstWithin)'s private members the class
tt(FirstWithin) cannot simply use tt(friend class SecondWithin), as
tt(SecondWithin)'s definition is as yet unknown. A i(forward declaration) of
tt(SecondWithin) is required and this forward declaration must be provided by
the class tt(Surround), rather than by the class tt(FirstWithin).
Clearly, a forward declaration like `tt(class SecondWithin)' makes no
sense in the class
tt(FirstWithin) itself, as this would refer to an external
(global) class tt(SecondWithin). Likewise, the
forward declaration of the nested class tt(SecondWithin) cannot be provided
inside
tt(FirstWithin) as tt(class Surround::SecondWithin). Doing so would generate
the following error message:
quote(`Surround' does not have a nested type named `SecondWithin')
Here the class tt(SecondWithin) must be declared by the class tt(Surround),
before the class tt(FirstWithin) has been defined. This way tt(SecondWithin)'s
friend declaration is accepted inside tt(FirstWithin).
The following example shows the classes having full access to all private
members of all classes:
verb(
class Surround
{
class SecondWithin;
static int s_variable;
public:
class FirstWithin
{
friend class Surround;
friend class SecondWithin;
static int s_variable;
public:
int value();
};
friend class FirstWithin;
int value();
private:
class SecondWithin
{
friend class Surround;
friend class FirstWithin;
static int s_variable;
public:
int value();
};
friend class SecondWithin;
};
inline int Surround::value()
{
FirstWithin::s_variable = SecondWithin::s_variable;
return s_variable;
}
inline int Surround::FirstWithin::value()
{
Surround::s_variable = SecondWithin::s_variable;
return s_variable;
}
inline int Surround::SecondWithin::value()
{
Surround::s_variable = FirstWithin::s_variable;
return s_variable;
}
)
|