C++ syntax of derivation

1
2
3
4
class base
{
//...base class members
}
1
2
3
4
class Derived: access-specifier Base
{
//...derived class members
}

the base class is also called the super class. The class that derives from the base, also known as the derived class, can be called the subclass.

e.g. a simple inheritance hierarchy

demolist_10.1

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
using namespace std;

class Fish
{
public:
bool isFreshWaterFish;
void Swim()
{
if (isFreshWaterFish)
cout << "swim in lake" << endl;
else
cout << "swim in ocean" << endl;
}
};

class Tuna : public Fish
{
public:
Tuna() // constructor
{
isFreshWaterFish = false;
}
};

class Crap : public Fish
{
public:
Crap()
{
isFreshWaterFish = true;
}
};

int main()
{
Crap MyLunch;
Tuna MyDinner;
cout << "Lunch: ";
MyLunch.Swim();
cout << "Dinner: ";
MyDinner.Swim();

return 0;
}

neither of the two derived class seems to define a method Swim() but we have managed to successfully invoke in main(). This is because Swim() is a public member of base class Fish that they inherit form.

access Specifier Keyword protected

protected, like public and private, is also an access specifier. When class attributes or functions are declared as protected, you are effectively making it accessible to classes derive (and friends), simultaneously making it inaccessible to everyone else outside the class, including main().

e.g. A better class using protected based on demolist_10.1 .

demolist_10.2

modifying line 4-15

1
2
3
4
5
6
7
8
9
10
11
12
13
class Fish
{
protected:
bool isFreshWaterFish;//accessbile only to derived classes
public:
void Swim()
{
if (isFreshWaterFish)
cout << "swim in lake" << endl;
else
cout << "swim in ocean" << endl;
}
};

base classes initialization

using initialization lists and invoking the appropriate base class constructor via the constructor of the derived class.

Syntax as shown in the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base
{
public:
Base(int someNumbers)//overloaded constructor
{
//use someNumbers
}
};
class Derived: public Base
{
public:
Derived: Base(25);//instantiate Base with argument 25
{
//derived class constructor code
}
};

derived class constructor with initialization lists

demolist_10.3

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>3
using namespace std;

class Fish
{
protected:
bool isFreshWaterFish;

public:
Fish(bool isFreshWater) : isFreshWaterFish(isFreshWater) {}

void Swim()
{
if (isFreshWaterFish)
cout << "swim in lake" << endl;
else
cout << "swim in ocean" << endl;
}
};

class Tuna : public Fish
{
public:
Tuna() : Fish(false) {}
};

class Crap : public Fish
{
public:
Crap() : Fish(true) {}
};

int main()
{
Tuna MyLunch;
Crap MyDinner;

cout << "Lunch ";
MyLunch.Swim();
cout << "Dinner ";
MyDinner.Swim();

return 0;
}

Fish now has a constructor that take a default parameter initializing Fish::isWaterFreshFish. Thus the only possibility to create an object of Fish is via providing it a parameter that initialized the protected member. This way class Fish ensures that the protected member doesn't contain a random value.

derived class overriding base class's method

class derived overrides the method in class base. syntax as shown in following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base
{
public:
void DoSomething()
{
//...implementation code... Does something
}
};
class Derived: public Base
{
public:
void DoSomething()
{
//...implementation code... Does something else
}
};

Thus, if method DoSomething() were to invoked using instance of Derived, then it wouldn't invoke the functionality in class Base.

Derived class overriding the method in Base class demolist10_4

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
using namespace std;

class Fish
{
protected:
bool isFreshWaterFish;

public:
Fish(bool isFreshWater) : isFreshWaterFish(isFreshWater) {}

void Swim()
{
if (isFreshWaterFish)
cout << "swim in lake" << endl;
else
cout << "swim in ocean" << endl;
}
};

class Tuna : public Fish
{
public:
Tuna() : Fish(false) {}
void Swim()
{
cout << "Tuna swim" << endl;
}
};

class Crap : public Fish
{
public:
Crap() : Fish(true) {}
void Swim()
{
cout << "Crap swim" << endl;
}
};

int main()
{
Tuna MyLunch;
Crap MyDinner;

cout << "Lunch ";
MyLunch.Swim();
cout << "Dinner ";
MyDinner.Swim();

return 0;
}

The code demonstrates that the implementation of Fish::Swim() in the base class Fish is overridden by the identical function Swim() defined by the classes Tuna and Carp that derive from Fish. The only way to invoke Fish::Swim() is by having main() use the scope resolution operator (::) in explicitly invoking Fish::Swim().