Monday, November 21, 2011

Inheritance

inherited Member
derived Member


As you can see, when we constructed Derived, the Base portion of Derived got constructed first.


 const variables must be initialized with a value at the time of creation


access specifier



Adding new functionality


Redefining functionality
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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; }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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:
1
2
3
4
5
6
7
8
9
10
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
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.
Hiding functionality
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.

1
2
3
4
5
6
7
8
9
10
11
12
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:
1
2
3
4
5
6
7
8
int main()
{
    Derived cDerived(7);
    // PrintValue is public in Derived, so this is okay
    cDerived.PrintValue(); // prints 7
    return 0;
}

We can also use this to make public members private:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
}

11.7 — Multiple inheritance


Problems with multiple inheritance

Is multiple inheritance more trouble than it’s worth?
As it turns out, most of the problems that can be solved using multiple inheritance can be solved using single inheritance as well. Many object-oriented languages (eg. Smalltalk, PHP) do not even support multiple inheritance. Many relatively modern languages such as Java and C# restricts classes to single inheritance of normal classes, but allow multiple inheritance of interface classes (which we will talk about later). The driving idea behind disallowing multiple inheritance in these languages is that it simply makes the language too complex, and ultimately causes more problems than it fixes.

No comments:

Post a Comment