Bruce Eckel's Thinking in C++, 2nd Ed | Contents | Prev | Next |
//: C05:Friend.cpp // Friend allows special access struct X; // Declaration (incomplete type spec) struct Y { void f(X*); }; struct X { // Definition private: int i; public: void initialize(); friend void g(X*, int); // Global friend friend void Y::f(X*); // Struct member friend friend struct Z; // Entire struct is a friend friend void h(); }; void X::initialize() { i = 0; } void g(X* x, int i) { x->i = i; } void Y::f(X* x) { x->i = 47; } struct Z { private: int j; public: void initialize(); void g(X* x); }; void Z::initialize() { j = 99; } void Z::g(X* x) { x->i += j; } void h() { X x; x.i = 100; // Direct data manipulation } int main() { X x; Z z; z.g(&x); } ///:~
//: C05:NestFriend.cpp // Nested friends #include <cstdio> #include <cstring> // memset() using namespace std; #define SZ 20 struct Holder { private: int a[SZ]; public: void initialize(); struct Pointer { private: Holder* h; int* p; public: void initialize(Holder* h); // Move around in the array: void next(); void previous(); void top(); void end(); // Access values: int read(); void set(int i); }; friend Holder::Pointer; }; void Holder::initialize() { memset(a, 0, SZ * sizeof(int)); } void Holder::Pointer::initialize(Holder* h) { h = h; p = h->a; } void Holder::Pointer::next() { if(p < &(h->a[SZ - 1])) p++; } void Holder::Pointer::previous() { if(p > &(h->a[0])) p--; } void Holder::Pointer::top() { p = &(h->a[0]); } void Holder::Pointer::end() { p = &(h->a[SZ - 1]); } int Holder::Pointer::read() { return *p; } void Holder::Pointer::set(int i) { *p = i; } int main() { Holder h; Holder::Pointer hp, hp2; int i; h.initialize(); hp.initialize(&h); hp2.initialize(&h); for(i = 0; i < SZ; i++) { hp.set(i); hp.next(); } hp.top(); hp2.end(); for(i = 0; i < SZ; i++) { printf("hp = %d, hp2 = %d\n", hp.read(), hp2.read()); hp.next(); hp2.previous(); } } ///:~