Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a derived class call protected member function in this code?

Tags:

c++

oop

#include <iostream>

class Base
{  
protected:
    void somethingProtected()
    {
        std::cout << "lala" << std::endl;
    }
};

class Derived : public Base
{
public:
    void somethingDerived()
    {
        Base b;
        b.somethingProtected();    // This does not compile
        somethingProtected();      // But this is fine
    }
};

int main()
{
    Derived d;
    d.somethingDerived();
    return 0;
}

I thought that maybe only the protected members of this can be used and protected members of other instances are forever unreachable.

But:

class Derived : public Base
{
public:

    void somethingDerived(Derived& d)
    {
        d.somethingProtected();  // This compiles even though d is
                                 // potentially a different instance
    }

    void somethingDerived(Base& b)
    {
        b.somethingProtected();  // This does not
    }
};

I feel kind of nauseated by this, since I have been programming in C++ for some time, but I could not find any explanation for this behaviour.

EDIT:

It doesn't matter if it is the same or a different instance:

int main()
{
    Derived d1, d2;          // Two different instances
    d1.somethingDerived(d2); // This compiles fine
    d1.somethingDerived(d1); // This compiles fine
    return 0;
}

EDIT2:

It seems that when it comes to access rights, it doesn't matter at all what instance of a class is being used:

class Base
{
public:
    void something(Base& b)  // Another instance
    {
        ++b.a;               // But can enter private members
    }

private:
    int a;
};
like image 626
Martin Drozdik Avatar asked May 28 '13 06:05

Martin Drozdik


People also ask

Can a derived class access protected members?

Protected members in a class are similar to private members as they cannot be accessed from outside the class. But they can be accessed by derived classes or child classes while private members cannot.

Do derived classes inherit protected members?

protected inheritance makes the public and protected members of the base class protected in the derived class. private inheritance makes the public and protected members of the base class private in the derived class.

Can we access protected member derived class in Java?

Protected Access Modifier - Protected Variables, methods, and constructors, which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class. The protected access modifier cannot be applied to class and interfaces.

How do you call a protected function in C++?

protected function call c++ Bookmark this question. Show activity on this post. Class Base() { protected: void foo(); } Class Derived : public Base { void bar(); } void Derived::bar(){ foo(); //this causes an error. }


3 Answers

Even though access control in C++ works on per-class basis (as opposed to per-instance basis), protected access specifier has some peculiarities.

The language specification wants to ensure that you are accessing a protected member of some base subobject that belongs to the derived class. You are not supposed to be able access protected members of some unrelated independent objects of base type. In particular, you cannot access protected members of freestanding objects of base type. You are only allowed to access protected members of base objects that are embedded into derived objects as base subobjects.

For this reason, you have to access protected members through pointer->member syntax, reference.member or object.member syntax, where the pointer/reference/object refers to the derived class.

This means that in your example, protected member somethingProtected() is not accessible through Base objects, Base * pointers or Base & references, but it is accessible through Derived objects, Derived * pointers and Derived & references. Your plain somethingProtected() access is allowed, since it is just a shorthand for this->somethingProtected() where this is of type Derived *.

b.somethingProtected() violates the above requirements.

Note that in accordance with the above rules in

void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}

the first call will also fail while the second one will compile, even though both are trying to access the same entity.

like image 84
AnT Avatar answered Oct 10 '22 12:10

AnT


I believe you have some confusion on how to access base class members. It is only this way:

class Derived : public Base
void drivedMethod() {
    Base::baseMethod();
}

in your example you are trying to access a protected member of another instance.

a Derived instance will have access to it's own protected members but not to another class instance protected members, this is by design.

In fact accessing the protected members of another class, from another instance members or from the main function are in fact both under public access...

http://www.cplusplus.com/doc/tutorial/inheritance/ (look for the access specifier table to see the different levels)

Both examples prove the same thing for example:

void somethingDerived(Base& b)
    {
        b.somethingProtected();  // This does not

here your Derived class is getting b as a parameter, so it is getting another instance of base, then because b.somethingProtected is not public it will not complie..

this will complie:

void somethingDerived()
{
   Base::somethingDerived();

your second example complies fine because you are accessing a public method on another d class

>  void somethingDerived(Base& b)
>     {
>         b.somethingProtected();  // This does not
>     }
like image 3
Dory Zidon Avatar answered Oct 10 '22 12:10

Dory Zidon


The Derived class can only access the protected base member in Derived objects. It cannot access the member in objects that are not (necessarily) Derived objects. In the cases that fail, you are trying to access the member via a Base &, and since this might refer to an object that is not Derived, the access can't be made.

like image 2
Chris Dodd Avatar answered Oct 10 '22 12:10

Chris Dodd