Search

11.6 — Adding, changing, and hiding members in a derived class

In the introduction to inheritance lesson, we mentioned that one of the biggest benefits of using derived classes is the ability to reuse already written code. You can inherit the base class functionality and then add new functionality, modify existing functionality, or hide functionality you don’t want. In this lesson, we’ll take a closer look at how each of these things is done.

First, let’s start with a simple base class:

Now, let’s create a derived class that inherits from Base. Because we want the derived class to be able to set the value of m_value when derived objects are instantiated, we’ll make the Derived constructor call the Base constructor in the initialization list.

We’ll develop Derived over the course of this lesson.

Adding new functionality

In the above example, because we have access to the source code of the Base class, we can add functionality directly to Base if we desire.

There may be times when we have access to a base class but do not want to modify it. Consider the case where you have just purchased a library of code from a 3rd party vendor, but need some extra functionality. You could add to the original code, but this isn’t the best solution. What if the vendor sends you an update? Either your additions will be overwritten, or you’ll have to manually migrate them into the update, which is time-consuming and risky.

Alternatively, there may be times when it’s not even possible to modify the base class. Consider the code in the standard library. We aren’t able to modify the code that’s part of the standard library. But we are able to inherit from those classes, and then add our own functionality into our derived classes. The same goes for 3rd party libraries where you are provided with headers but the code comes precompiled.

In either case, the best answer is to derive your own class, and add the functionality you want to the derived class.

One obvious omission from the Base class is a way for the public to access m_value. We could remedy this by adding an access function in the Base class -- but for the sake of example we’re going to add it to the derived class instead. Because m_value has been declared as protected in the Base class, Derived has direct access to it.

To add new functionality to a derived class, simply declare that functionality in the derived class like normal:

Now the public will be able to call getValue() on an object of type Derived to access the value of m_value.

This produces the result:

derived has value 5

Although it may be obvious, objects of type Base have no access to the getValue() function in Derived. The following does not work:

This is because there is no getValue() function in Base. Function getValue() belongs to Derived. Because Derived is a Base, Derived has access to stuff in Base. However, Base does not have access to anything in Derived.

Redefining functionality

When a member function is called with a derived class object, the compiler first looks to see if that member exists in the derived class. If not, it begins walking up the inheritance chain and checking whether the member has been defined in any of the inherited classes. It uses the first one it finds.

Consequently, take a look at the following example:

This prints

I am a Base
I am a Base

When derived.identify() is called, the compiler looks to see if function identify() has been defined in the Derived class. It hasn’t. Then it starts looking in the inherited classes (which in this case is Base). Base has defined an identify() function, so it uses that one. In other words, Base::identify() was used because Derived::identify() doesn’t exist.

However, if we had defined Derived::identify() in the Derived class, it would have been used instead. This means that we can make functions work differently with our derived classes by redefining them in the derived class!

In our above example, it would be more accurate if derived.identify() printed “I am a Derived”. Let’s modify function identify() in the Derived class so it returns the correct response when we call function identify() with a Derived object.

To modify a function the way a function defined in a base class works in the derived class, simply redefine the function in the derived class.

Here’s the same example as above, using the new Derived::Identify() function:

I am a Base
I am a Derived

Note that when you redefine a function in the derived class, the derived function does not inherit the access specifier of the function with the same name in the base class. It uses whatever access specifier it is defined under in the derived class. Therefore, a function that is defined as private in the base class can be redefined as public in the derived class, or vice-versa!

Adding to existing functionality

Sometimes we don’t want to completely replace a base class function, but instead want to add additional functionality to it. In the above example, note that Derived::identify() completely hides Base::identify()! This may not be what we want. It is possible to have our derived function call the base version of the function of the same name (in order to reuse code) and then add additional functionality to it.

To have a derived function call a base function of the same name, simply do a normal function call, but prefix the function with the scope qualifier (the name of the base class and two colons). The following example redefines Derived::identify() so it first calls Base::identify() and then does its own additional stuff.

Now consider the following example:

I am a Base
I am a Base
I am a Derived

When derived.identify() is executed, it resolves to Derived::identify(). However, the first thing Derived::identify() does is call Base::identify(), which prints “I am a Base”. When Base::identify() returns, Derived::identify() continues executing and prints “I am a Derived”.

This should be pretty straightforward. Why do we need to use the scope resolution operator (::)? If we had defined Derived::identify() like this:

Calling function identify() without a scope resolution qualifier would default to the identify() in the current class, which would be Derived::identify(). This would cause Derived::identify() to call itself, which would lead to an infinite loop!

There’s one bit of trickiness that we can run into when trying to call friend functions in base classes, such as operator<<. Because friend functions of the base class aren’t actually part of the base class, using the scope resolution qualifier won’t work. Instead, we need a way to make our Derived class temporarily look like the Base class so that the right version of the function can be called.

Fortunately, that’s easy to do, using static_cast. Here’s an example:

Because a Derived is-a Base, we can static_cast our Derived object into a Base, so that the appropriate version of operator<< that uses a Base is called.

This prints:

In derived
In base
7

Changing an inherited member’s access level

C++ gives us the ability to change an inherited member’s access specifier in the derived class. This is done by using a using declaration to identify the (scoped) base class member that is having its access changed in the derived class, under the new access specifier.

For example, consider the following Base:

Because Base::printValue() has been declared as protected, it can only be called by Base or its derived classes. The public can not access it.

Let’s define a Derived class that changes the access specifier of printValue() to public:

This means that this code will now work:

Two notes:

First, you can only change the access specifiers of base members the derived class would normally be able to access. Therefore, you can never change the access specifier of a base member from private to protected or public, because derived classes do not have access to private members of the base class.

Second, as of C++11, using-declarations are the preferred way of changing access levels. However, you can also change access levels by using an “access declaration”. This works identically to the using declaration method, but omits the “using” keyword. This access declaration way of redefining access is now considered deprecated, but you will likely see older code using this pattern, so it’s worth knowing about.

Hiding functionality

In C++, it is not possible to remove functionality from a base class other than by modifying the source code. However, in a derived class, it is possible to hide functionality that exists in the base class, so that it can not be accessed through the derived class. This can be done simply by changing the relevant access specifier.

For example, we can make a public member private:

Note that this allowed us to take a poorly designed base class and encapsulate its data in our derived class. Alternatively, instead of inheriting Base’s members publicly and making m_value private by overriding its access specifier, we could have inherited Base privately, which would have caused all of Base’s member to be inherited privately in the first place.

For functions, you can also mark functions as deleted in the derived class, which ensures they can’t be called at all through a derived object:

Conclusion

In a derived class, it’s possible to add new functionality, redefine existing functionality, change the access levels of inherited members, and hide inherited functionality.

Most of the time, you’ll just be adding new functionality, but it’s useful to know that the other options exist if you need them.

11.7 -- Multiple inheritance
Index
11.5 -- Inheritance and access specifiers

33 comments to 11.6 — Adding, changing, and hiding members in a derived class

  • Kinten

    ok, the only diference in private and protected inheritance is while making multiple inheritances? say yo got:

    base -> derived1 -> derived2 (diagram)

    if derived1 does Private inheritance then derived2 can’t acces anything from base class, otherwise if I make derived1 Protected derived2 will have acces, but not the program.
    I am right?

    • Kinten

      Multiple inheritance was’t the right word, it shold be “multiple times derived”

    • If derived1 does private inheritance, than derived2 can’t access anything from the base class, as you say.

      If derived1 uses protected inheritance, then public and protected members in the base class become protected in derived1. This means that they can be accessed by derived2. Note that neither derived1 nor derived2 can access private members in base.

      In reality, it is pretty uncommon to see private and protected inheritance. Almost all of the inheritance you see is done via public inheritance.

  • Thanks again for this absolutely wonderful tutorials!

  • rahul nagar

    Hi Alex,

    First of all I would like to thank u on the wonderful tutorials ..It really helped me… Just a small Doubt in this part

    Base::PrintValue;

    Here in above you have tried to change the access specifier to public by defining it into the public section of the derived class. However I tried the same and its giving me error .

    class Base
    {
    public:
    int m_a;
    Base(int a=0): m_a(a)
    {
    cout<<"\n I am in base constructor \t"<<m_a<<endl;
    }
    protected:
    void identify()
    {
    cout<<"\n I am in base class \t"<<m_a<<endl;
    }
    };

    class Derived :public Base
    {
    public:
    int m_b;
    Derived(int a=0,int b=0):Base(a),m_b(b)
    {
    cout<<"\n I am in Derived constructor \t"<<m_b<<endl;
    }
    Base::identify;
    };
    int main()
    {
    Derived d_obj(7,9);
    d_obj.identify();
    return 0;
    }

    Below are the errors ::

    Error 433: "inheritance.cpp", line 26 # The class name in an access declaration must be a base class.
    Derived::identify;
    ^^^^^^^^^^^^^^^^^^
    Error 182: "inheritance.cpp", line 36 # "int main()" cannot access protected member "void Base::identify()".
    d_obj.identify();
    ^^^^^^^^^^^^^^^^

    Please suggest on the same.

  • ACCESS MODIFIERS FINALLY UNDASTAND U (PRIVATE, PROTECTED, PUBLIC)….

    THANKS ALOT..

    ALMIGHTY GOD THANKS ALOT…FOR GIVING ME DE WISDOM….

    EXCELLENT TUTORIAL BY MR.ALEX…. GOD IS YOUR STRENGTH….

  • Sheena Chhabra

    It is written "Therefore, a function that is defined as private in the base class can redefined as public in the derived class, or vice-versa!"

    But the derived class can not access private members/functions of base class . so how is it possible ?

    • Alex

      If a function is private in the base class and reimplemented as public in the derived class, the derived version will be callable externally, but it won’t be able to access private members from the base class (after all, they are private). There no rule-breaking here.

  • Alex Silva

    Hi Alex

    Can I redefine a member variable in the derived class?

    • Alex

      I’m not sure what you mean by “redefine” in this context. You can’t have a derived class change the type of a variable in the base class, but you can declare a member variable with the same name. This member variable will shadow the variable in the base class with the same name.

  • Reaversword

    I’ve been thinking about this, trying to reach a "logical-intuitive" example.

    This is my example, but it includes some questions that get this topic a little bit "out of the limits", I think.

    4 classes:

    Grandfather (60 year old man, owner of a shop)
    Father (32 years old man, co-owner of a shop)
    Son1 (8 years old boy, still doesn’t know exactly what he does, no dental caries diagnosed).
    Son2 (10 years old boy, still doesn’t know exactly what he does, dental caries diagnosed).

    Grandfather has:
    dentures (private), safeDepositBox (protected), tv (protected), candies (public).

    Father has access to all except dentures.

    But, I confess I’m unable to get this working (cause I’m looking for the limits):

    *This lesson answers question 1.

    1*) How can Father "private" the son to get access to safeDepositBox, but let him use tv?
    (This would be get 2 base protected members, and get one private, and other still protected, but this would be per-member, and not per-class).

    2) How can Father "private" the Son2 to get access to candies (because dental caries), but still be able to offer it to Son1?
    (This would be a member-private for one derived class, but available for the other derived one).

    3) How can Father "private" the Sons to get access to candies (because dental caries), but still be able to offer it to public?
    (This would be a member-private for derived classes, but available for the public).

    Are any of this two last cases possible?. Or this is go to much out of the limits / rules?.

    • Alex

      > How can Father “private” the son

      I don’t know what this means. Are you asking how Son can derived from Father, keeping safeDepositBox private but keeping tv protected? If Father doesn’t want anybody to inherit access to the safeDepositBox by default, he could redefine it as private. But the Son could still override it.

      Essentially, access controls are there to help enforce good encapsulation, not to strictly keep derived classes in or out.

      • Reaversword

        I was asking how Father prevent Son access to safeDepositBox, but still leaves him use tv. But this is perfectly answered here.

        Father just redeclares safeDepositBox as private , and do nothing with tv (because is already declared as "protected" by Grandfather).

        So, interesting ones (and I think a little bit out of limits) are 2) and 3).

  • Lokesh

    @Alex
    In the "Redefining functionality" section, I think this line needs review:
    "Therefore, a function that is defined as private in the base class can redefined as public in the derived class, or vice-versa!"
    A function that is defined as private in base class cannot be accessed by the derived class let alone redefining it.

    • Alex

      I think you’re misunderstanding the case I’m talking about. I’m not talking about changing the access specifier of the base class function (that’s covered in the subsection “Hiding functionality”). I’m talking about adding a new function in the derived class with the same name as the one in the base class, with its own implementation.

      For example, this code works fine:

  • Lokesh

    Oh. Got it. Yes, you are right, I misunderstood it as changing the access specifier. Thanks!
    So, if a function is defined as private in base class and we define the same function as public in the derived class such as the print() in the above example, we are essentially defining a "new" member function of the derived class with the same signature as some private function in base class but with different access specifier.

  • Xhevo

    Hi, Alex.
    It is not quite clear to me the last paragraph of 11.6 - Adding, changing, and hiding members in a derived class:… you can only change the access specifiers of base members…, and then: …you can never change the access specifiers of base members from private to protected or public,…
    [
    One word of caution: you can only change the access specifiers of base members the class would normally be able to access. Therefore, you can never change the access specifier of a base member from private to protected or public, because derived classes do not have access to private members of the base class.
    ]      My best wishes for your excellent job.

    • Alex

      A derived class can’t change the access specifier for a private base class member variable because it doesn’t have access to do so.
      However, a derived class can change the access specifier for a public (or derived) base class member variable because it does have access to do so.

  • Dinesh

    Hi,
    Does hiding a base class member or function affect their base class in general or does it only take effect when the derived class is used?
    For example:
    Base
    {
    Public:
    Int m_bPublic;
    Base(int bValue=0): m_bPublic(bValue)
    {}

    }
    Derived: Public Base
    {
    Private:
    Base:: m_bPublic;
    Public:
    Derived(int value): Base(value)
    {}

    }
    Int Main
    {
    Derived derClass(5);
    // Made d member variable of base as private
    Base baseClass(3);
    //Is the below line allowed?
    baseClass.m_bPublic=6;
    }

    On a different note, I would like to appreciate your efforts for creating such an excellent tutorial. Thank You and Cheers 🙂

  • Nima

    Hello.
    Thanks for your great teaching.
    I have a question from hiding functionality part of your tutorial:
    Is there any difference between use or not using keyword before Base::m_nValue in order to transfer one  or more field(s)\method(s) from protected Base class to private Derived class?
    for example:
    class Derived: Base
    {
        using Base::m_nValue;
    }
    Thanks in advance.

  • Connor

    Hi Alex, I don’t understand why we are using the ‘using’ keyword when redefining the access specifier on inherited members.

    why do we use ‘using’. Also, why does c++ not include the braces when re-specifying access of a member function i.e.

    Thanks for the help :).

    • Alex

      In this context, the using keyword tells the code that we want to use the base class function at this new access level. C++ doesn’t seem to like to create new keywords (that may cause naming conflicts with existing programs) so they often overload existing ones.

      I’m guessing the parenthesis are not needed because you don’t need to respecify the parameters. Having empty parenthesis implies no parameters, which isn’t necessarily the case.

  • Matt

    In the code example directly above section "Adding to existing functionality", in the main function, you wrote a comment:
    "// calls B::print(), which is public".

    I think you meant to write "calls Derived::print()…"

  • Sivasankar

    Hi Alex,

    Thanks for the tutorial. I have a small doubt.

    At the line no 25 in 2nd example of "Hiding functionality" section,
    Is "int getValue() = delete;" equivalent to placing the line "using Base::getValue;" under private in derived class ? So that public cann’t call getValue using derived object

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter