Here is a very simple code demonstrating how 'protected' is used

# include <iostream>
using namespace std;

class A
{
        protected :
                int a;
};

class B : public A
{
        public :

                void f_1()          //    *
                {
                        a = 10;
                        cout << a;
                }
};

int main()
{
        B obj_2;
        obj_2.f_1();    //    **

        return 0;
}

*This function here, f_1(), puts the value 10 inside the variable 'a' of object obj_2 present here **. That is, it changes the value of 'a' of the invoking object

But mind you, 'a' is inherited as it is protected in the base class 'A'

But if I change my program to this, that is, only change the function f_1() to this

# include <iostream>
using namespace std;

class A
{
        protected :
                int a;
};

class B : public A
{
        public :

                void f_1()
                {
                        A obj;          //    This part changed!!
                        obj.a = 20;     //    Made a seperate object,
                        cout << obj.a;  //    instead of using the invoked object
                }
};

int main()
{
        B obj_2;
        obj_2.f_1();

        return 0;
}

Then it gives this error error: `int A::a' is protected So can someone please explaing why this error is occuring?

Recommended Answers

All 7 Replies

I think there is no need to dig up a place in the C++ standard where it says something like: "a class Foo derived from class Bar cannot access the protected members of Bar from another object of type Bar or any other of its derived class, including Foo." Because this is obvious. The "protected" access rights are limited to the instance of the derived class. In other words, a Foo object can access ITS OWN protected members that IT GOT from ITS inheritance of Bar. For any other object that is not the "this" object, protected members are inaccessible, just like if they were private, as far as Foo is concerned or any other derived class for that matter.

This is required for encapsulation. It would be far too dangerous to allow all objects of classes derived from Bar to be able to temper with the protected members of other objects inheriting from Bar. Think about it, if that was allowed, you could easily make a dummy class derived from Bar, to do some operation on the protected members of all the other classes derived from Bar, that totally breaks encapsulation.. As they say, "with great power comes great responsibility", well a golden rule in programming is "when it is easy to do the wrong thing, don't trust any programmer to do the right thing, especially not yourself!" and access right is one of the features of C++ that tries to give you tools to help you help yourself by blocking access to things you should not try to access.

commented: Nice explanation. +4

For any other object that is not the "this" object, protected members are inaccessible, just like if they were private, as far as Foo is concerned or any other derived class for that matter.

What you say is not completely correct, for the following code compiles and runs.

#include <iostream>

using namespace std;

class A { protected: int x; };
class B: public A {
public:
    B(int x) { this->x = x; }
    int get_this() const { return x; }
    int get_that(B const& obj) const { return obj.x; }
    int get_local() const {
        B obj(30);
        return obj.x;
    }
    friend int get_friend(B const& obj) { return obj.x; }
};

int main() {
    B obj1(10), obj2(20), obj3(40);
    cout<< obj1.get_this() <<endl
        << obj1.get_that(obj2) <<endl
        << obj1.get_local() <<endl
        << get_friend(obj3) <<endl;
}

Within the definition of the derived class or friends of the derived class, non-public members of other objects of the same class type are accessible. Non-public members of objects of other class types, including the base class, are still not accessible.

Okay Mike, I got what you said. I raised this question because I got an assignment which i think, is related to this. Check this out.

  1. Create a generic base class called LinkedList for integer values
  2. It stores pointer to list and integer value
  3. It also declares two pure virtual functions, store() and retrieve()
  4. Create two derived classes called Stack and SortedList (in ascending order) that inherit from LinkedList
  5. Write a main() function to create a stack of integers and a sorted list of integers

Now see point 2, it says that the class contains a self-referential pointer and an integer data. Or in other words

class LinkedList
{
    protected :
        int data;
        LinkedList * link;
    
    public    :
        virtual void store    ( int number ) = 0;  //    According to point 3
        virtual int  retrieve ( void       ) = 0;
};

But class Stack and class SortedList will override the inherited functions of LinkedList
Then let us consider only one case, the case of class Stack

  • I'll first override the function store() of class Stack
  • Since, an object of this class will act as the ADT Stack, the function store() will act as the function push()
  • But the stack will be implemented as a linked list
  • Hence, i will create node, put data in node and then link it. But there is a problem
  • As i have to create a node, it should be of type LinkedList and not Stack, because the variables are of LinkedList type
    class Stack
    {
        public :
            void store(int number)
            {
                LinkedList * new_address = new LinkedList;  //  <- BUT THIS
                new_address -> data = number;               //  STEP IS ILLEGAL
                new_address -> link = NULL;                 //  HOW TO BYPASS THIS STEP?
                
                if(link == NULL)        //  IF THE STACK IS EMPTY
                {                       //  PUTTING THE NEW DATA ON TOP
                    link = new_address;
                }
                else
                {
                    ...
                }
            }
    }

So you see that I cannot proceed with this program in this fashion.
However, I've found a solution. I just put those variables (int data and *link) in each of the derived classes and made pointer objects of their respective classes
But here I'm modifying the question
So, in a nutshell, all that I'm asking is that, can the problem be solved without changing the question?

Simple.

If you are implementing a Stack as a linked list, then every link in the list has to be a Stack too (and similarly for a SortedList). So the new link that you make with "new LinkedList" (which is of course illegal) you can create with "new Stack" or "new SortedList". Then, you will actually be able to access the protected member "link" in that newly created Stack or SortedList because the compiler knows they are of that type because you just created it. To help, if it doesn't work (i.e. your compiler is not clever enough), you can declare "new_address" as "Stack*" or "SortedList*".

Are you talking about this?

class LinkedList
{
    protected :
        int data;
        LinkedList * link;
    public :
        virtual void store(int n) = 0;
        virtual int  retrieve()   = 0;
};

class Stack : public LinkedList
{
    public :
        void store(int n)
        {
            Stack * new_add = new Stack;  //  THIS STEP IS STILL
            new_add -> data = n;          //  GIVING ME ERROR
            new_add -> link = NULL;

            if(link == NULL)
            {
                link = new_add;
            }
            else
            {
                ...
            }
        }
};

This is not working. And I think it's not working because it's not the invoked object (Like you said!). I can only access protected members of invoked objects. It's giving me this error error: `int LinkedList::data' is protected

Then use RAII (Resource Allocation Is Initialization). Make a constructor for Stack and SortedList that takes both data members it needs (data and link). This way, you do:

Stack* new_address = new Stack(number,NULL); //BTW, just a hint, NULL is probably not what you want link to be set to for the linked list to work.

This assignment is all about polymorphism, which is an extension of inheritance. To create polymorphism you must declare a pointer to a base class object, then store a pointer to a derived class object in it.

LinkedList * new_add = new Stack;

Once you have done that, you will be able to access public members of the base class using an object of derived type as well as the derived type's public members. From inside the derived object, you will then be able to access protected members of the base class and protected/private members of the derived class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.