C++ – Accessing Virtual Protected Functions of Base Class in Derived Class

access-modifierscc++11inheritance

Consider the following:

#include <iostream>

class Base {
    public:

        void go(){this->doSomething();}

    protected:
        virtual void doSomething(){std::cout << "base";}
};

class DerivedA : public Base {
    protected:
        void doSomething() override {std::cout << "a";}
};

class DerivedB : public Base {
    public:
        Base * basePtr;

        DerivedB()
          :basePtr(new DerivedA())
        {}

    protected:
        void doSomething() override {basePtr->doSomething();} // wont compile
};

int main(int , char *[])
{
   DerivedB b;
   b.go();
}

doSomething() in the DerivedB subclass will not compile, but I do not understand why this behavior exists! I am trying to access a virtual protected member function of my base class, which I would have thought would be allowed.

http://en.cppreference.com/w/cpp/language/access

In the section on protected member access, it says

"A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)"

According to point 2, if I cast down to the subclass (DerivedA), this would be allowed but I would then be in conflict with the condition that I am accessing a protected member function of a different class (which is not a base class, and would also not compile). Worse, if I knew the sub class type of the derived object, I could still not access it even if I cast to its common base.

Why is this behavior enforced? I assume it is probably going to be a side effect of allowing multiple inheritance etc but I can't think of exactly what it would be. It's annoying because now I have to make a public interface for something which is and should only be used by base or derived classes, which goes against the point of inheritance and access modifiers.

Best Answer

I am trying to access a virtual protected member function of my base class

Yes, but you are trying to do this via another object basePtr, not this object. And that other object is a Base. You somehow mix up classes (types) with objects (instances) of that class. You shouldn't be able to call a protected member function of a Base object when you're not 'in' that same object. And you aren't. The fact that you are executing code inside your derived class doesn't matter here. The access level is not being checked against the instance this of your derived class, but against the instance basePtr you want to access.

And it's fine the way it is. Designers of class Base don't want people to call doSomething on objects of class Base. No matter from where! That's what the word protected says. They are however fine by having doSomething be called from the implementation of instances that are (in the the sense of the is-a-relationship of inheritance) Bases, that means from instances of derived classes.

Related Topic