Q1. What do the lines 1 to 12 do ? Will any of them generate any error ? If
yes, then why ?

line 1
------
The default constructor of the class Smurf is invoked.

line 2
------
The 1-argument constructor of the class GenderedSmurf is invoked. Since this
constructor does not explicitly invoke any constructor of its parent (the
class from which it is derived), the default constructor of class Smurf is
invoked. 

line 3
------
The 2-argument constructor of the class AgedSmurf is invoked. The 2-argument
constructor of class AgedSmurf invokes the 1-argument constructor of
GenderedSmurf, which in turn invokes the default constructor of Smurf class.

line 4
------
harmony is an instance of type Smurf. And Smurf has a public member function
Sing(). So, it is perfectly legal to invoke that member function from outside
the class. The function that gets invoked is Smurf::Sing().

line 5
------
Same as line 4

line 6
------
smurfette is an instance of type GenderedSmurf and IsMaleSmurf() is a public
member function of GenderedSmurf. So, it is legal to call that function from
the client code.

line 7
------
smurfette is an instance of type GenderedSmurf, and GenderedSmurf is derived
from the class Smurf. So, all the fields (data members) and the functions of
Smurf are inherited by GenderedSmurf. So, effectively, the class GenderedSmurf
also has a member function Sing(), which it inherited from the class Smurf.
So, it is alright to invoke smurfette.Sing(). The function which gets invoked
is Smurf::Sing().

line 8
------
papa is an instance of AgedSmurf and AgedSmurf has a public member function
IsPapaSmurf(). So, there's nothing wrong with this line.

line 9
------
smurfette is an instance of GenderedSmurf. GenderedSmurf does not define any
member function with the name IsPapaSmurf(). So, go up the hierarchy, ie the
class from which GenderedSmurf was derived ie the class Smurf. Even Smurf does
not have any member function with the name IsPapaSmurf(). Thus it is a
compilation error. 
    One might think that AgedSmurf has been derived from GenderedSmurf and
AgedSmurf has a function IsPapaSmurf(). So, one should be able to invoke that
function using an instance of GenderedSmurf. NO, if class B is derived from
class A, then class B implicitly has all the data and function members of
class A. But it is not the other way around. Since AgedSmurf is derived from
GenderedSmurf, AgedSmurf can see what is there in GenderedSmurf, but
GenderedSmurf cant see what is there in AgedSmurf.

line 10
-------
gender is a protected variable in class GenderedSmurf. When AgedSmurf is
derived from GenderedSmurf, AgedSmurf inherits all the data and function
members of GenderedSmurf. So, it inherits the variable gender also. And it
continues to be protected inside the class AgedSmurf. And we know that
protected members cant be accessed directly from client code. So, it will give
a compilation error.


line 11
-------
compilation error. The explaination is again the same as that for line 9

line 12
-------
papa is an instance of AgedSmurf. And it has a public member function Sing().
This is AgedSmurf::Sing(). Also since AgedSmurf is derived from GenderedSmurf
and GenderedSmurf is derived from Smurf, it also has the function
Smurf::Sing().

thus, papa.Sing() invokes AgedSmurf::Sing()
and papa.Smurf::Sing() would invoke Smurf::Sing()

If there were no function Sing() defined in the class AgedSmurf. Then
papa.Sing() would have invoked Smurf::Sing()

Q2. Which class would you modify if you wanted all Smurfs to be able to change
the Song they can sing ?

Ans. Inheritance tells me that if I define a function setSong() in the class
Smurf, then it will be inherited by the class GenderedSmurf, which in turn
will be inherited by the class AgedSmurf. Thus if we add a single setSong()
function to the class Smurf, it seems that it would do the job. 

Some of you suggested during the section that one could add a setSong()
function to each of the three classes. But, then the whole objective of having
inheritance will be lost. One of the main motivations for inheritance is to
avoid just this kind of redundancy. 

Q3  (modified)  Which class would you modify if you
wanted GenderedSmurf and AgedSmurf to be the only smurf who can change their
song?

Ans. There was some confusion about this question in the section. There was a
small goof up with the question. So, the answer is to add a method setSong
(string song) in the class GenderedSmurf. This is inherited by AgedSmurf,
which enables AgedSmurf also to change the song.

This question originally was 'which class would you modify if you wanted
smurfette to be the only Smurf which could change its song. So, there does
exist an answer to it. And the answer is same as the one for the modified Q3.
The answer actually lies in the implementation of AgedSmurf::sing(). An
AgedSmurf always sings out the same thing irrespective of what is there in the
songWords field. So, even if an AgedSmurf manages to change its songWords
field using the function setSong() which it inherits from GenderedSmurf, the
AgedSmurf is always going to sing out the same thing "Dum diddiley I-O".

Q4. How would you change AgedSmurf::IsPapaSmurf() if gender was private
instead of protected ?

Ans. Look at the second clause in the if condition in
AgedSmurf::IsPapaSmurf(). It looks like 'gender == MALE'. Now when gender was
a protected member of class GenderedSmurf, and since AgedSmurf is derived from
GenderedSmurf, AgedSmurf is able to access the member gender directly. But
once it becomes a private variable, the condition 'gender == MALE' is going to
flag a compilation error. Because the private variables of a class cannot be
accessed directly even in the classes which are derived from it. So, the
condition 'gender == MALE' can be replaced by IsMaleSmurf() because this
function essentially does the same thing.