As the designer of base class, you may hesitate whether to use private or protect access control. Then, let's try the following examples:

1. Call protected member function

#include <cstdio>

class A
{
protected:
    void b() {printf("Oops!\n");}
};

void f(A* a)
{
    class A_hack:public A
    {
        friend void f(A*);
    };
    static_cast<A_hack *>(a)->b();
}

class B
{
public:
    void f(A* a)
    {
        class A_hack:public A
        {
            friend B;
        };
        static_cast<A_hack *>(a)->b();
    }
};

int main()
{
    f(NULL);
    B().f(NULL);
}

Although the result of the cast is undefined as stated in the standard, if no this pointer adjustment happens and the layout of A is the same as A_hack which are normally the case, the code will break the access control.

For the evil user, his purpose is archieved.

2. Call pure virtual function

class A
{
protected:
    virtual void Fun() =0;
};

class B:public A
{
public:
    B() {Dummy();}

private:
    void Dummy() {Fun();}
};
class C:public B
{
public:
    virtual void Fun() {}
};

int main()
{
    C c;
}

Do you ever wonder how to call pure virtual function? Do you like to see what does _purecall in VC do? Just try the above code.

The problem here is because of the protect access of "Fun" in base class. Of course, you should not call virtual function in ctor (they will not have polymorphic behavior), but when you call Dummy in ctor, you may not realize the fact that Dummy will call virtual function internally. Then the disaster happens.

If what you want by using virtual is to allow the derived class to provide some specific behavior, you'd better declare the function as private.

Although both the above code are nonconformant, they at least show the possibility that your user can do more than what you expect for protect.

If you don't even have confidence with private (Like evil #define private public which definitely violates One Definition Rule), you'd better use the PImpl Idiom to implement your interface.