Because C is essentially also an A, and any A can do Func().
B is neither a friend of C, nor is derived from C. In fact, B and C are
completely independent, except that they share the same base class. Now recall
how protected works. If you use protected, it means that *only* that class
or its descendends will be allowed access. So if you allow B to access
C::Func() , it will violate this rule, because B is neither C not C's
descendant. C is A, and A can do Func() and so can C, but B cant' call
C::Func(), because it would violate the rules for protected. Virtual functions
can never lead to a situation where it can violate access rules.
It will be even more obvious with data members. Consider
class A {
protected:
int m;
// the rest
};
If in B you try bar->m, you will be accessing C's m. m may be in A, but
it is C's protected member. Why should B be allowed access to it ? If C went
class C: public A {
protected:
int n;
// etc.
};
you couldn't access n from B. Why can you access m ?
Think of it like this: If Y is X, Y can access X's protected members.
B is B, so B can access B's protected members. B is A, so B can access
A's protected members. B is not C, so B can't access C's protected members.
What if A had also a non-virtual Func2(A *that), also protected, which
calls that->Func(). Then in B::Foo I can do this->Func2(bar). I don't
see the problem in there, yet I would get the same situation as above.
Here A is calling Func() and through A*. What A is doing is calling its
own Func(), virtual function mechanism results in calling of a different
Func(). In B::Foo(A* bar), you are not calling through B*, you are calling
through A*. bar may be B*, maybe not. If it is not, you can't access it.
But I don't always want bar to be of type B, I want bar to be of any
type A - that is, A or derived from A. That's all I need to know that
it supports Func(). Otherwise there's no point in putting Foo as pure
virtual in A, I could just as well have made it a private function in
B.
But it will violate encapsulation. You just can't go about accessing other
classes protected functions just because they happen to share your base class.
If you could, it would violate encapsulation. Assume that you have a class
library, for example MFC. Now you wish to access the protected members of the
classes in the library. So you inherit a class from CObject, and begin to
access the protected methods of all the classes (those inherited from
CObject). Should such misuse be permitted ?
If you want to access Func(), you must make it public.
-Arijit