5

From http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html#faq-19.5

A member (either data member or member function) declared in a protected section of a class can only be accessed by member functions and friends of that class, and by member functions and friends of derived classes

So, what is the way to access the protected function fun in the derived class?

#include <iostream>
using namespace std;

class X
{
    private:
        int var;
    protected:
        void fun () 
        {
            var = 10;
            cout << "\nFrom X" << var; 
        }
};

class Y : public X
{
    private:
        int var;
    public:
        void fun () 
        {
            var = 20;
            cout << "\nFrom Y" << var;
        }

        void call ()
        {
            fun ();

            X objX;
            objX.fun ();
        }
};

This results in:

anisha@linux-dopx:~/> g++ type.cpp
type.cpp: In member function ‘void Y::call()’:
type.cpp:9:8: error: ‘void X::fun()’ is protected
type.cpp:32:14: error: within this context

I saw this: Accessing protected members in a derived class

Given:

You can only access protected members in instances of your type (or derived from your type). You cannot access protected members of an instance of a parent or cousin type.

In your case, the Derived class can only access the b member of a Derived instance, not of a different Base instance.

Changing the constructor to take a Derived instance will also solve the problem.

How can this be accomplished without changing the constructor declaration?

Community
  • 1
  • 1
Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411

6 Answers6

7

One solution is to add friend class Y to X.

Anycorn
  • 50,217
  • 42
  • 167
  • 261
6

I think that the thing you are trying to do should looks like this:

#include <iostream>
using namespace std;

class X
{
    private:
        int var;
protected:
    virtual void fun () 
    {
        var = 10;
        cout << "\nFrom X" << var; 
    }
};

class Y : public X
{
private:
    int var;
public:
    virtual void fun () 
    {
        var = 20;
        cout << "\nFrom Y" << var;
    }

    void call ()
    {
        fun ();


        X::fun ();
    }
};

That way you can invoke hiden member from your base class. Otherwise you have to add friend X as it was pointed in other post.

0lukasz0
  • 3,155
  • 1
  • 24
  • 40
  • +1. yes. X::fun() is the way to access a hidden name from a base class X. No friends or temporary objects required. – Johan Lundberg Feb 04 '12 at 11:10
  • 4
    This is a completely different use case. This is calling `X::fun` on `*this`, not calling it on an object of type `X` that isn't a base class of a `Y` object which is what is being attempted in the question. – CB Bailey Feb 04 '12 at 12:48
  • 1
    I don't see how this can be accepted as the answer, like @CharlesBailey says, it's a completely different use case. – Neutrino Apr 15 '16 at 13:24
2

See this example:

#include <iostream>
using namespace std;

class X {
  private:
    int var;
  protected:
    void fun () 
    {
      var = 10;
      cout << "\nFrom X" << var; 
    }
};

class Y : public X {
  private:
    int var;
  public:
    void fun () 
    {
      var = 20;
      cout << "\nFrom Y" << var;
    }

    void call ()
    {
      fun(); /* call to Y::fun() */
      X::fun (); /* call to X::fun() */

      X objX;
      /* this will not compile, because fun is protected in X        
      objX.fun (); */

    }
};

int main(int argc, char ** argv)  {
  Y y;
  y.call();
  return 0;  
}

This yields

From Y20
From X10

Because you have overloaded the fun()-method in Y, you have to give the compiler a hint which one you mean if you want to call the fun-method in X by calling X::fun().

jupp0r
  • 4,502
  • 1
  • 27
  • 34
1

In void Y::call ()

    X objX;
    objX.fun (); 

// here you're trying to access the protected member of objX , this/current object of Y doesn't contains objX as it's base object , they both are different objects. That is why you can't access its member.

you can make Y friend of X as a solution told by @anycom.

Edit: what I mean is, from inside Y (which is inherited from X) , you can simply call protected/public members of "it's" base class X i.e you're accessing it's base members simply. But That doesn't means you can now access the protected members of all objects of type X, since you're trying to access those members from outer scope of class X i.e via object of X. You know all these rules but it seem you did too much thinking 0_o

Mr.Anubis
  • 5,132
  • 6
  • 29
  • 44
  • `this/current object of Y doesn't contains objX as it's base object ` What does that statement mean? – Aquarius_Girl Feb 04 '12 at 10:41
  • @AnishaKaul every object has a pointer `this` which point to itself as you already know. X is base class of Y, then object of Y will contain sub-Object of class `X`. In your code `Y` has base class `X`, it can access protected/pubic members of it's **base class** `X` **only** inside the scope of `Y` but can't access any protected/private members of object `X` (which you created in your code) just like you can't access private member of `Y` from `main` – Mr.Anubis Feb 04 '12 at 15:14
  • @AnishaKaul Read this too : http://msdn.microsoft.com/en-us/library/x9wzb5es%28v=vs.80%29.aspx – Mr.Anubis Feb 04 '12 at 15:24
1

Well, if friend is ok, then this angle may as well be ok:

#include <iostream>

class X {
private:
    int var;
protected:
    virtual void fun() {
        var = 10;
        std::cout << "\nFrom X" << var;
    }

    static void Fun(X& x) {
        x.fun();
    }
};

class Y : public X {
private:
    int var;
public:
    virtual void fun() {
        var = 20;
        std::cout << "\nFrom Y" << var;
    }

    void call() {
        fun();
        X objX;
        objX.fun(); /* << ne-ne */
        Fun(objX); /* << ok */
    }
};

Of course, be mindful of the type you pass to X::Fun if you use this as-is.

justin
  • 104,054
  • 14
  • 179
  • 226
-1

You are not accessing protected function in your derived class, you are trying to overload it and promote from protected to public. This is a forbidden action, you only can hide functions in derived class, e.g. overload protected function as a private.

Accessing protected function means call it from some member of a class:

class Y : public X
{
public:
    void call() {
      fun();
    }
}

or like you call it by objX.fun(); is also correct.

Mikhail
  • 20,685
  • 7
  • 70
  • 146