Do Sub-Classes Really Inherit Private Member Variables?

27,921

Solution 1

Basically as far as I know, when you create a base class with a public, protected, and private section and variables/functions in each the public and protected sections will get inherited into the appropriate section of the sub-class (defined by class subclass : private base, which will take all public and private members of base and put them into public, changing the word private to public puts them all in public and changing it to protected puts them all into protected).

There's a bit of confusion in this statement.

Recall that inheritance is defined for classes and structs in C++. Individual objects (ie. instances) do not inherit from other objects. Constructing an object using other objects is called composition.

When a class inherits from another class, it gets everything from that class, but the access level of the inherited fields may inhibit their use within the inheritor.

Furthermore, there are 3 kinds of inheritance for classes: private (which is the default), protected, and public. Each of them changes the access level of a class properties and methods when inherited by a subclass.

If we order the access levels in this manner: public, protected, private, from the least protected to the most protected, then we can define the inheritance modifiers as raising the access levels of the inherited class fields to at least the level they designate, in the derived class (ie. the class inheriting).

For instance, if class B inherits from class A with the protected inheritance modifier:

  class B : protected A { /* ... */ };

then all the fields from A will have at least the protected level in B:

  • public fields become protected (public level is raised to protected),
  • protected fields stay protected (same access level, so no modification here),
  • private fields stay private (the access level is already above the modifier)

Solution 2

"When you create a sub-class you never receive anything from the private section of the [base class]. If this is true then an object of the sub-class should never have it's own version of a private variable or function from the base class, correct?"

No. The derived class inherits all the members of the base class, including the private ones. An object of the inherited class has those private members, but does not have direct access to them. It has access to public members of the base class that may have access to those members, but it (the derived class) may not have new member functions with such access:

class yourClass : public myClass
{
public:
  void playByTheRules()
  {
    setMyVariable(); // perfectly legal, since setMyVariable() is public
  }

  void tamperWithMyVariable()
  {
    myVariable = 20; // this is illegal and will cause a compile-time error
  }
};

Solution 3

myObject and yourObject are two different objects! Why should they share anything?

Think about it that way: Forget about inheritance and suppose you have a class Person with private int age; and public void setAge (int age) {...}. You then instantiate two objects:

Person bob;
Person bill;
bob.setAge(35);

Would you expect Bill to be 35 now, too? You wouldn't, right? Similarly, your myObject doesn't share its data with yourObject.


In response to your comment:

The class yourClass inherits from myClass. That means that both yourObject and myObject have their own myVariable, the latter obviously by definition, the former inherited from myClass.

Solution 4

Physically, every single member( including member functions) of base class goes into the subclass. Doesn't matter if they are private. Doesn't matter if you inherit them publically/protected-ly/privately. So in your example, yourClass contains all three of getMyVariable(), setMyVariable() and myVariable. All this is pretty simple, okay?

What matters is how we can access them. It is like when a file is deleted on your system. So, you should first understand the difference between a member being not there and a member being there but inaccessible. Assume for now that all inheritance takes place publically. Then, all public members of base class are public in derived class, protected members are protected and private members are inaccessible. They are inaccessible and not non-existent because there can be some member functions in protected and public sections in base class which access the private members of base class. Thus, we need all those private members of base which are accessed by public and protected member functions of base, for their functionality. Since there is no way that we can determine which member is needed by which member function in a simple manner, we include all private members of the base class in derived class. All this simply means that in a derived class, a private member can be modified by only through the base class' member functions.

Note: every private member has to be accessed, directly or indirectly [through another private member function which in turn is called by a public/protected member function] by a public/protected meber function, else it has no use.

So, we know till now that a private member variable of base class has its use in derived class i.e. for the functionality of its public/protected member functions. But they can't be accessed directly in base class.

Now, we turn our attention to private/public inheritance. For public inheritance, it means that all the accessible members of base class (that is, the public and protected members) can not be at a level more permissive than public. Since, public is the most permissive level, public and protected members remain public. But at protected and private inheritance, both become protected and private in the derived class, respectively. Inthe latter case, since all these members are private, they can't be accessed further in the hierarchy chain, but can be accessed by the given derived class all the same.

Thus, the level of each base class member in derived class is the lesser of their level in derived class () and the type of inheritance (public/protected/private).

Same concept applies to the functions outside the class. For them private and protected members are inaccessible but they do exist and can be accessed by the public member functions.

And taking your case as a final example, setMyvariable() and getMyVariable() can access myVariable in the derived class. But no function specified in derived class can access myVariable. Modifying your class:

class myClass
{
public:
  void setMyVariable();
  int getMyVariable();
private:
  int myVariable;
};

class yourClass : public myClass
{
public:
  // void yourFunction() { myVariable = 1; }
  /*Removing comment creates error; derived class functions can't access myVariable*/
};

Further: you can add exceptions to the type of inheritance too e.g. a private inheritance except a member made public in derived class. But that is another question altogether.

Solution 5

You never call myObject.setMyVariable(), so myObject.getMyVariable() will not return 15.

private does not imply static.

Share:
27,921
TorbenC
Author by

TorbenC

I have been learning C++ on and off since May of 2012 and I have found programming to be one of my true passions. I have done a little work on a project called OpenMW (an engine reimplementation for The Elder Scrolls III: Morrowind) in the AI department, and I have also learned SDL for the most part. I am eager to learn OpenGL now, but it will have to wait for a little while (currently figuring out how to do collision with a fixed timesteps). I absolutely love stackoverflow and I am very happy such a site exists; Stackoverflow has helped me a lot. Thank you!

Updated on July 05, 2022

Comments

  • TorbenC
    TorbenC almost 2 years

    Basically as far as I know, when you create a base class with a public, protected, and private section and variables/functions in each the public and protected sections will get inherited into the appropriate section of the sub-class (defined by class subclass : private base, which will take all public and protected members of base and put them into public, changing the word private to public puts them all in public and changing it to protected puts them all into protected).

    So, when you create a sub-class you never receive anything from the private section of the previous class (the base class in this case), if this is true then an object of the sub-class should never have it's own version of a private variable or function from the base class correct?

    Let's run over an example:

    #include <iostream>
    
    class myClass     // Creates a class titled myClass with a public section and a private section.
    {
    public:
      void setMyVariable();
      int getMyVariable();
    private:
      int myVariable;     // This private member variable should never be inherited.
    };
    
    class yourClass : public myClass {};    // Creates a sub-class of myClass that inherits all the public/protected members into  the
    // public section of yourClass. This should only inherit setMyVariable()
    // and getMyVariable() since myVariable is private. This class does not over-ride any
    // functions so it should be using the myClass version upon each call using a yourClass
    // object. Correct?
    
    int main()
    {
      myClass myObject;           // Creates a myClass object called myObject.
      yourClass yourObject;       // Creates a yourClass object called yourObject
      yourObject.setMyVariable(); // Calls setMyVariable() through yourObject. This in turn calls the myClass version of it    because
      // there is no function definition for a yourClass version of this function. This means that this
      // can indeed access myVariable, but only the myClass version of it (there isn't a yourClass
      // version because myVariable is never inherited).
    
      std::cout << yourObject.getMyVariable() << std::endl;   // Uses the yourClass version of getMyVariable() which in turn
      // calls the myClass version, thus it returns the myClass myVariable
      // value. yourClass never has a version of myVariable Correct?
    
      std::cout << myObject.getMyVariable() << std::endl;     // Calls the myClass version of getMyVariable() and prints myVariable.
    
      return 0;
    }
    
    void myClass::setMyVariable()
    {
      myVariable = 15;        // Sets myVariable in myClass to 15.
    }
    
    int myClass::getMyVariable()
    {
      return myVariable;      // Returns myVariable from myClass.
    }
    

    Now, in theory based on what I think, this should print: 15 15 Due to it simply always using the myClass version of the functions (thus using the myClass myVariable). But, strangely, this is not the case. The result of running this program prints: 15 0 This makes me wonder, are we actually not only inheriting myVariable, but do we also have the ability to mess around with it? Clearly this is creating an alternate version of myVariable somehow otherwise there wouldn't be a 0 for the myClass version. We are indeed editing a second copy of myVariable by doing all this.

    Can someone please explain this all to me, this has torn apart my understanding of inheritance.

  • chris
    chris over 11 years
    Well, it cooould... I know what you mean, though :)
  • TorbenC
    TorbenC over 11 years
    That's the point of this question, why is it that yourObject.getMyVariable returns 15? This means there are two instances of myVariable, otherwise no matter which object you used to set/get it would return 15 on both. Clearly there are two myVariables somehow, that is the question.
  • TorbenC
    TorbenC over 11 years
    OH!!!!! No wonder, it is two different object, that's why! Each object has it's own instance of the functions and such. So am I right that myVariable is never inherited? I just want to clear that up, is my understanding of inheritance correct?
  • us2012
    us2012 over 11 years
    It is inherited, see Beta's answer!
  • TorbenC
    TorbenC over 11 years
    Interesting, so can you access the private members that were inherited through an alternative method? I mean, can I access the myVariable in yourClass in anyway? I see what you mean, but wouldn't getMyVariable just access the base class's version of myVariable instead of accessing the yourclass version? I've read that you cannot use any private member variables that are inherited into the sub-class (researched more after your post).
  • us2012
    us2012 over 11 years
    You can't use them in the implementation of the subclass. You can of course use them in the implementation of the base class though, and call public methods/access public fields of the base class from the outside.
  • TorbenC
    TorbenC over 11 years
    Right right, but what I mean is, how can you access and modify the sub-class's version of the private members it inherits?
  • us2012
    us2012 over 11 years
    There is only one version of the private member. The subclass inherits the member from the base class, there is nothing like a second copy. Behind the scenes, what you're actually accessing and modifying is the base class's version. (This does not mean that your yourObject is somehow accessing myObject, they are different objects!)
  • TorbenC
    TorbenC over 11 years
    Ahh so it is similar to inheriting a public function, you gain access to it (though in this case not directly) but you don't get your own version of it unless your over-ride it?
  • TorbenC
    TorbenC over 11 years
    Wow, thank you very much for the useful post. That explained everything perfectly! (thank you all really but this one got the best answer)
  • TorbenC
    TorbenC over 11 years
    Thank you very much for the little addition there, everything all makes sense now. Thank you too!
  • Jatin
    Jatin about 6 years
    Great answer ! Very clear & covered every aspect of question.