A friend of a class X is a function or class that is not a member of X, but is granted the same access to X as the members of X. Functions declared with the friend specifier in a class member list are called friend functions of that class. Classes declared with the friend specifier in the member list of another class are called friend classes of that class.
A class Y must be defined before any member of Y can be declared a friend of another class. In the following example, the friend function print is a member of class Y and accesses the private data members a and b of class X.
#include <iostream> using namespace std; class X; class Y { public: void print(X& x); }; class X { int a, b; friend void Y::print(X& x); public: X() : a(1), b(2) { } }; void Y::print(X& x) { cout << "a is " << x.a << endl; cout << "b is " << x.b << endl; } int main() { X xobj; Y yobj; yobj.print(xobj); }
a is 1 b is 2
You can declare an entire class as a friend. Suppose class F is a friend of class A. This means that every member function and static data member definition of class F has access to class A.
In the following example, the friend class F has a member function print that accesses the private data members a and b of class X and performs the same task as the friend function print in the above example. Any other members declared in class F also have access to all members of class X.
#include <iostream> using namespace std; class X { int a, b; friend class F; public: X() : a(1), b(2) { } }; class F { public: void print(X& x) { cout << "a is " << x.a << endl; cout << "b is " << x.b << endl; } }; int main() { X xobj; F fobj; fobj.print(xobj); }
a is 1 b is 2
class F; class X { friend class F { }; };
class A { void g(); }; void z() { class B { friend void f() { }; // error }; } class C { friend void A::g() { } // error friend void h() { } };The compiler accepts the definition of h(), but not the function definition of f() or g().
You cannot declare a friend with a storage class specifier.
class F; class G; class X1 { //C++98 friend declarations remain valid in C++0x. friend class F; //Error in C++98 for missing the class-key. friend G; }; class X2 { //Error in C++98 for missing the class-key. //Error in C++0x for lookup failure (no previous class D declaration). friend D; friend class D; };
class C;
template <typename T, typename U> class F {
//C++0x compiles sucessfully.
//Error in C++98 for missing the class-key.
friend T;
//Error in both C++98 and C++0x: a template parameter
//must not be used in an elaborated type specifier.
friend class U;
};
F<C> rc;
F<char> Ri;
class Derived;
typedef Derived D;
class C;
typedef C Ct;
class Base{
public:
Base() : x(55) {}
//C++0x compiles sucessfully.
//Error in C++98 for missing the class-key.
friend D;
//Error in both C++98 and C++0x: a typedef name
//must not be used in an elaborated type specifier.
friend class Ct;
private:
int x;
};
struct Derived : public Base {
int foo() { return this->x; }
};
int main() {
Derived d;
return d.foo();
}
struct T { }; namespace N { struct A { friend T; }; }In this example, if this feature is in effect, the friend declaration statement does not declare a new entity T, but looks for T. If there is no T found, then the compiler issues an error. Consider another example:
struct T { }; namespace N { struct A { friend class T; //fine, no error }; }In this example, the friend declaration statement does not look for T outside namespace N, nor does it find ::T. Instead, this statement declares a new class T in namespace N.