I'm pretty sure the book is wrong and/or it was a typo (or you're reading it wrong?)
When you do this:
int mem(D1 d) { return d.i; }
You're accessing Base::i, not D1::i. Since Frnd is a friend of Base, it's ok.
Or perhaps it was a typo in the book. Maybe he meant to say this:
int mem(D1 d) { return d.j; } // error: friendship doesn't inheri
This
would definitely be an error because here you're trying to access D1::j, which is protected. Even though Frnd is a friend of Base, it is not a friend of D1, so this gets you an error. This is what "friendship doesn't inherit" means; just because you're a friend of the parent, doesn't mean you're a friend of the children.
Another tricky bit is this:
1 2 3 4 5 6 7 8 9 10
|
class D1 : public Base {
using Base::i; // throw this in here....
protected:
int j;
};
class Frnd {
public:
int mem(D1 d) { return d.i; } // now this will error..
};
|
The idea here is that the using statement makes Base::i
"become" D1::i. So now mem is trying to access D1::i, which is an error.
However this is dumb because it's easily side-stepped:
1 2 3 4 5
|
int mem(D1 d)
{
Base& b = d;
return b.i; // we just got around it
}
|