How to access protected method in base class from derived class?

28,426

Solution 1

Protected members in a base-class are only accessible by the current object.
Thus, you are allowed to call this->foo(), but you are not allowed to call this->b->foo(). This is independent of whether Derived provides an implementation for foo or not.

The reason behind this restriction is that it would otherwise be very easy to circumvent protected access. You just create a class like Derived, and suddenly you also have access to parts of other classes (like OtherDerived) that were supposed to be inaccessible to outsiders.

Solution 2

Normally, you would do it using Base::foo(), which refers to the base class of the current instance.

However, if your code needs to do it the way you're trying to and it's not allowed, then you'll need to either make foo() public or make Derived a friend of Base.

Solution 3

One solution would be to declare a static protected function in Base that redirects the call to the private / protected function (foo in the example).

Lets say:

class Base {
protected:
    static void call_foo(Base* base) { base->foo(); }
private:
    virtual void foo() = 0;
};

class Derived : public Base {
private:
    Base* b;
protected:
    virtual void foo(){/* Some implementation */};
    virtual void foo2()
    {
        // b->foo(); // doesn't work
        call_foo(b); // works
    }
};

This way, we don't break encapsulation because the designer of Base can make an explicit choice to allow all derived classes to call foo on each other, while avoiding to put foo into the public interface or explicitly turning all possible subclasses of Base into friends.

Also, this method works regardless of whether foo is virtual or not, or whether it is private or protected.

Here is a link to a running version of the code above and here another version of the same idea with a little more business logic.

Solution 4

It's a bit fragile, but with the classes you defined here, won't this work?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}

The reinterpret_cast points at the VTABLE for the base object, and calls it through this members accessor.

Share:
28,426

Related videos on Youtube

Bernard Rosset
Author by

Bernard Rosset

user573152

Updated on July 09, 2022

Comments

  • Bernard Rosset
    Bernard Rosset almost 2 years

    Here is a sample of code that annoys me:

    class Base {
      protected:
        virtual void foo() = 0;
    };
    
    class Derived : public Base {
      private:
        Base *b; /* Initialized by constructor, not shown here
                    Intended to store a pointer on an instance of any derived class of Base */
    
      protected:
        virtual void foo() { /* Some implementation */ };
        virtual void foo2() {
          this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
        }
    };
    

    How do you access to the protected overrided function?

    Thanks for your help. :o)

    • GWW
      GWW over 13 years
      I don't think your implementation is quite right. Why do you have an instance of Base as a member variable? this->b->foo() would be trying to call a pure virtual method.
    • 341008
      341008 over 13 years
      This program shouldn't compile. You cannot instantiate an abstract class....Unless b is pointing to an instance of some other class derived from Base.
    • underscore_d
      underscore_d over 5 years
      C++ calls them member functions, not methods (although some people use the latter, but in my experience that just leads to linguistic arguments), and the concepts are the same for member functions and member variables, so: duplicate of Accessing protected members in a derived class
  • Jonathan Wood
    Jonathan Wood over 13 years
    But the OP's code doesn't refer to the base class of the current instance. He's accessing another instance, which presumably is a derived class that implements the pure-virtual function. (Otherwise, the instance could not be created.)
  • Gemini14
    Gemini14 over 13 years
    @Jonathan Wood I understand what you're saying, but just going from the code he's posted, it looks like he's trying to instantiate an abstract base class (Base) and call a pure virtual function (Base::foo()), which is a no-no (as GWW and 341008 also mentioned above).
  • Bernard Rosset
    Bernard Rosset over 13 years
    Thanks, I now clearly understand the reasons of the restriction... That would be a security hole... big one!
  • DrYap
    DrYap about 10 years
    Please don't think of it as a security hole. Access modifiers do not provide any security, you could just read the memory location if you wanted the data.
  • underscore_d
    underscore_d over 5 years
    right, this isn't about "security" but instead about telling users which parts of the class they can use and rely on (i.e. which parts are not implementation details that might vanish/change at any moment). sure, they shouldn't read that stuff, and will have to use acrobatics with stuff like offsetof to do so, but it's definitely not about security in the sense of physically preventing access to data - only documenting intended usage, semantics, and stability of the API.