Navigation



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 this is done.

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

#include <iostream>
using namespace std;

class Base
{
protected:
    int m_nValue;

public:
    Base(int nValue)
        : m_nValue(nValue)
    {
    }

    void Identify() { cout << "I am a Base" << endl; }
};

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

class Derived: public Base
{
public:
    Derived(int nValue)
        :Base(nValue)
    {
    }
};

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

Adding new functionality

Because we have access to the source code of the Base class, we could add functionality directly to Base. However, there may be times when we do not want to, or can not. 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. It’s also common to for developers to release header files containing class definitions, but release the implementation code precompiled — this means you can use the code, but you won’t have the ability to modify it directly.

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_nValue. Normally we’d write 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_nValue 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:

class Derived: public Base
{
public:
    Derived(int nValue)
        :Base(nValue)
    {
    }

    int GetValue() { return m_nValue; }
};

Now the public will be able to call GetValue() in order to access the value of m_nValue.

int main()
{
    Derived cDerived(5);
    cout << "cDerived has value " << cDerived.GetValue() << endl;

    return 0;
}

This produces the result:

cDerived 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:

int main()
{
    Base cBase(5);
    cout << "cBase has value " << cBase.GetValue() << endl;

    return 0;
}

This is because there is no GetValue() function in Base. 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 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:

int main()
{
    Base cBase(5);
    cBase.Identify();

    Derived cDerived(7);
    cDerived.Identify()

    return 0;
}

This prints

I am a Base
I am a Base

When cDerived.Identify() is called, the compiler looks to see if 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 a 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 cDerived.Identify() printed “I am a Derived”. Let’s modify Identify() so it returns the correct response when we call 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.

class Derived: public Base
{
public:
    Derived(int nValue)
        :Base(nValue)
    {
    }

    int GetValue() { return m_nValue; }

    // Here's our modified function
    void Identify() { cout << "I am a Derived" << endl; }
};

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

int main()
{
    Base cBase(5);
    cBase.Identify();

    Derived cDerived(7);
    cDerived.Identify()

    return 0;
}
I am a Base
I am a Derived

A word of warning: the prototype (return value, function name, and parameters) of the function in the derived class must be exactly identical to that in the base class. If the return value does not match, the compiler will issue an error. If the parameters or function name are different, C++ will treat this as an added function rather than a modified function!

Also 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 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 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 it’s own additional stuff.

class Derived: public Base
{
public:
    Derived(int nValue)
        :Base(nValue)
    {
    }

    int GetValue() { return m_nValue; }

    void Identify()
    {
        Base::Identify(); // call Base::Identify() first
        cout << "I am a Derived"; // then identify ourselves
    }
};

Now consider the following example:

int main()
{
    Base cBase(5);
    cBase.Identify();

    Derived cDerived(7);
    cDerived.Identify()

    return 0;
}
I am a Base
I am a Base
I am a Derived

When cDerived.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 is all pretty straightforward. The real lesson to take away from this is that if you want to call a function in a base class that has been redefined in the derived class, you need to use the scope resolution operator (::) to explicitly say which version of the function you want.

If we had defined Derived::Identify() like this:

    void Identify()
    {
        Identify(); // Note: no scope resolution!
        cout << "I am a Derived"; // then identify ourselves
    }

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!

Hiding functionality

In C++, it is not possible to remove functionality from a class. However, it is possible to hide existing functionality.

As mentioned above, if you redefine a function, it uses whatever access specifier it’s declared under in the derived class. Therefore, we could redefine a public function as private in our derived class, and the public would lose access to it. However, C++ also gives us the ability to change a base member’s access specifier in the derived class without even redefining the member! This is done by simply naming the member (using the scope resolution operator) to have it’s access changed in the derived class under the new access specifier.

For example, consider the following Base:

class Base
{
private:
    int m_nValue;

public:
    Base(int nValue)
        : m_nValue(nValue)
    {
    }

protected:
    void PrintValue() { cout << m_nValue; }
};

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

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

class Derived: public Base
{
public:
    Derived(int nValue)
        : Base(nValue)
    {
    }

    // Base::PrintValue was inherited as protected, so the public has no access
    // But we're changing it to public by declaring it in the public section
    Base::PrintValue;
};

This means that this code will now work:

int main()
{
    Derived cDerived(7);

    // PrintValue is public in Derived, so this is okay
    cDerived.PrintValue(); // prints 7
    return 0;
}

Note that Base::PrintValue does not have the function call operator (()) attached to it.

We can also use this to make public members private:

class Base
{
public:
    int m_nValue;
};

class Derived: public Base
{
private:
    Base::m_nValue;

public:
    Derived(int nValue)
    {
         m_nValue = nValue;
    }
};

int main()
{
    Derived cDerived(7);

    // The following won't work because m_nValue has been redefined as private
    cout << cDerived.m_nValue;

    return 0;
}

Note that this allowed us to take a poorly designed base class and encapsulate it’s data in our derived class.
(Alternatively, instead of inheriting Base’s members publicly and making m_nValue private by overriding it’s 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).

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.

11.7 — Multiple inheritance
Index
11.5 — Inheritance and access specifiers

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

  • Zafer

    I think the following statement about the last example is confusing: “Note that this allowed us to take a poorly designed base class and encapsulate it’s data in our derived class (alternatively, we could have inherited it privately instead).”

    The data is already inherited as private. Why did you say alternatively?

    • Note that Derived inherits Base publicly. This means that m_nValue would normally be inherited publicly. However, in the example, we overrode the access specifier to change it to private.

      Instead of inheriting Base publicly, we could have inherited Base privately. This would cause all of Base’s members to be inherited as private, which would essentially have the same effect.

      I changed the wording slightly to try to make this point clearer.

  • [...] 2007 Prev/Next Posts « Alex’s Threaded Comments WordPress Plugin v0.1 | Home | 11.6 — Adding, changing, and hiding members in a derived class » Monday, January 14th, 2008 at 1:09 [...]

  • weirdolino

    “When cDerived.GetClassName() is called, the compiler looks…”

    There is no GetClassName() function. I suppose it was what you originally wanted to name Identify()(?). Also, there’s a typo in the next line “Then it starts looks in the inherited classes…”

    • Yes, I renamed the function and forgot to update the text. Functions that begin with “Get” are usually accessor functions that return a value. Since this one didn’t, I renamed it Identify().

  • 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.

  • Supreame

    If the return value does not match, the compiler will issue an error.
    The return value of the Identify() function in the Derived class dosen’t have to be identical with the return value of Identify() from Base class . I tested it with VC Express 2008 compiler:

         int Identify() { cout << "I am a Derived" << endl; return 0;}
    

    and it compiles ok.

    Another thing, after cDerived.Identify() you forgot a “;” in this code part

    int main()
    {
        Base cBase(5);
        cBase.Identify();
    
        Derived cDerived(7);
        cDerived.Identify()
    
        return 0;
    }
    
  • Will

    in line 736:

     When a member function is called with a derived class object, the the compiler...
  • Pablo

    In the paragraph you start with “A word of warning…” It’s said that the type of the returned value by the function in the Base class must be the same type in the Derived class in order the compiler to not to issue an error, well, I’ve tried changing it and I’ve got no error, may it be dependent of the compiler used? or may be it is an overloaded function or a new definition of it in the Derived class!

  • Fred

    Please learn to spell “its” without an apostrophe. I cannot understand how someone could purport to understand the arcane syntax of C++, yet remain indifferent to the straightforward English syntax of apostrophes.

    • tylerfb11

      Which occurance are you refering to?
      BTW, I’m terible with grammar and such in Engilsh (my first language) but I can still code in C++. I just don’t really care a whole lot about proper ‘santax’ in everyday language becuase, with a little bit of common scence, anyone can esaliy figure out what you’re trying to say.

      -Tyler

  • typo:

    It’s also common [b]to[/b] for developers to release header files containing class definitions

    Thanks again for this absolutely wonderful tutorials!

  • [...] 11.6 Adding, changing, and hiding members in a derived class [...]

  • duetosideeffects

    I have a real question that I was hoping would’ve been asked in the comments, not just people picking at tiny errors in the tutorial…

    I have an inheritance chain
    NPC -> Drone
    I have overloaded the << operator, as a friend function, to output its info in the NPC (parent) class, then I created the Drone (child) class. When I make something like this

    Drone cDr01; cout << cDr01;
    

    Of course, it outputs all of the info kept in NPC as previously created, and nothing from Drone.
    If I re-overload the << operator in Drone, it overrides the NPC version. I also don't want to have to duplicate code, as in copy all of the previous code to the new one with the extra functionality, especially if I possibly wouldn't have access to it. I tried doing what was instructed above, to add the function call to the base in the derived version, but since it's an I/O operator, I can't seem to make it work.

    Basically, How do you add functionality to an overloaded << operator declared as a friend function.

  • duetosideeffects

    Like my first question, I found the answer simply by continuing the tutorials… :D So to anyone who read my question and wondered themselves how to do that, I think the answer is in lesson 12.1
    -(that’s where I got it, but it’s “I think” since I don’t know if it’s the most efficient/best way to do it)

    Inside the child class’s overloaded << operator, I created a reference variable NPC equal to the child class, then just simply outputted it.

    NPC operator<<

    ostream& operator<< (ostream &out, const NPC &cNPCTemp)
    {
    	out << ... << ... << ... << ...
    		// code that outputs stuff
    	return out;
    }
    

    Drone operator<<

    ostream& operator<< (ostream& out, Drone &cDrone)
    {
    	NPC &rNPC = cDrone;	//cuz of Hungarian I didn't have to think about the names
    	out << rNPC;
    
    	out << ... << ... << ... << ...
    		// code that outputs the Drone specific stuff
    	return out;
    }
    

    I am, however, running into an issue where if I try this with multiple inheritance, it calls the base (NPC) overloaded function more than once; I do have the classes in between virtual (chain is actually — NPC ->(Drone, Special) -> Enemy)
    Problem occurs when I call (cout << cEnemy) overloaded function.

    Is it possible, or is this one of the problems Multiple inheritance has?

  • 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.

  • [...] 11.6 — Adding, changing, and hiding members in a derived class    11.8 — Virtual base classes [...]

  • vvrao559

    Hi Rahul,

    It works

    I am in base constructor 7

    I am in Derived constructor 9

    I am in base class 7

  • prakash

    Alex,

    Excellent tutorial. It is at least at the same level with so many published books on c++ by well known authors.
    suggestions:
    1. I hope you can add more stuff on STL and BOOST, multi-threading, code optimization, design patterns, debugging tools.
    2. Also can add some ready made projects from academic level to more complicated ones.

    If you can do 1 and 2, it will be a unique site. I mean it will leave behind all the *.* books and tutorials on c++ even by well known authors.
    May be you can keep some part of the site as premium access.
    Any way…excellent site. Thank you.

    I found a minor bug on this page. :-)
    Missing a semicolon in the code on this page.

    int main()
    {
    Base cBase(5);
    cBase.Identify();

    Derived cDerived(7);
    cDerived.Identify()

    return 0;
    }

You must be logged in to post a comment.