01 January 2005

The meaning of "protected" seems to be quite simple and straight-forward: protected members can be accessed by either the same class or classes derived from the class. But in fact, it might be more complicated then you might have thought.

Can you explain the compilation result of the following C++ code, especially the two "Base" related functions.

class Base
{
  protected:
    void f() const { cout << "f" << endl;}
    static void sf() { cout << "sf" << endl;}
};

class D1 :public Base
{
};

class D2 : public Base
{
  public:
    void call_self() const
    {
        this->f();              // ok
    }

    void call_self(const D2& d2) const
    {
        d2.f();                 // ok
    }

    void call_base(const Base& b) const
    {
        b.f();                  // error
    }

    void call_base_sf(const Base& b) const
    {
        b.sf();                 // ok
    }

    void call_d1(const D1& d1) const
    {
        d1.f();                 // error
    }

    void call_d1_sf(const D1& d1) const
    {
        d1.sf();                // error
    }

};

The following words from The Java Programming Language (3e) (by Ken Arnold et al) reveal what "Protected" really means in java. It also holds true for C++.

… a protected member can also be accessed from a class through object references that are of at least the same type as the class – that is, references of the class's type or one of its subtypes. …

The reasoning behind the restriction is this: Each subclass inherits the contract of the superclass and expands that contract in some way. Suppose that one subclass, as part of its expanded contract, places some constraints on the values of protected member of the superclass. If a different subclass could access the protected members of objects of the first subclass then it could manipulate them in a way that would break the first subclass's contract – and this should not be permissible. Protected static members can be accessed in any extended class. … This is allowed because a subclass can't modify the contract of its static members as it can only hide them, not override them – hence there is no danger of another class violating that contract.

The C++ Programming Language special ed also has some words on this topic:

A derived class can access a base class protected members only for objects of its own type.

This prevents subtle errors that would otherwise occur when one derived class corrupts data belonging to other derived classes.

Above words give insight into the "protected" mechanism. However, you'd better make sure you really need a "protected" member. Generally speaking, "protected" is not a good choice. I remember that Bjarne Stroustrup had more words on that topic in The Design and Evolution of C++



blog comments powered by Disqus