Pagine

5 febbraio 2008

Lesson 4: Class inheritance

The topic of this new lesson is in my opinion the very heart of Object Orientation and consequently of C++.
In the previous lesson we discovered that a class is just a user-defined type which, along with storing information in its data members, is also able to perform actions on these members or on other objects through its member functions (a.k.a. methods).

Now that we know the basis, let's make things nicer and smarter.

Inheritance: from mother to daughter!


When you think about inheritance you have clearly in mind the transmission of properties from the mother to the daughter. This is exactly what happens when a (sub)class derives from a parent one. The derived class automatically includes all the methods and data members the parent's has plus its own. Let's consider the example shown in the picture at the beginning of the post: we have a mother class named CPolygon and several derived classes: CRectangle and CTriangle. Of course all the derived classes have something in common with the mother class, like for example being 2D shapes, but they are quite different one another (for instance, the number of sides).

How do we derive one class from another?


Very easily. First define the mother class in the usual way and when you have to define the derived class just put a colon (:) in its declaration according to the following syntax:

class DerivedClass : public MotherClass {

   // ....

};


The specifier public, just after the colon, can be replaced with private or protected. I will come on these in a moment, let me first show you a more real example.

// define here the mother class
class CPolygon {
 protected:

   // yes I know this is not valid in general,
   // but it's fair enough for now
   float _width;
   float _height;

 public:
   // the setter
   void setValues(float width, float height)
      { _width = width; _height = height; }

};

// define the derived classes
class CRectangle : public CPolygon {

 public:
   float area() { return _width * _height; }

};

class CTriangle : public CPolygon {

 public:
   float area() { return 0.5 * _width * _height ; }

};

int main(int, char**) {

   CRectangle myRectangle;
   CTriangle   myTriangle;

   myRectangle.setValues(10., 5.);
   myTriangle.setValues(5., 2.);

   cout << "The rectangle area is " << myRectangle.area() << endl;
   // you should get 50      
   cout << "The triangle area is " << myTriangle.area() << endl;    
   // now should be 5

   return 0;

}



As you can see, only in the base class we have explicitly defined the two data members and the setter method, while the derived classes get them automatically. In the derived classes we have defined an additional method: it is actually the same for both derived classes but with a different implementation!

Inheritance qualifiers

When we firstly defined a class, we said that all members of a class are private by default, if you want to make a member (either data or function) available to the user (through the "." or the "->" operator) you have to explicitly tag it as public. Ok, this is clear, but what is protected for? We use it in the previous example code in the declaration of the base class, but what does protected mean?

We didn't encountered the protected qualifier before because it is meaningful only with derived classes.
  1. A public member is available to all the other members of the same classes, of the derived ones and to external use (dot and arrow operators).
  2. A private member is available only to other members of the same class.
  3. A protected member is somehow in between. It's not available for external use (dot and arrow operators), but it is available to all the deriving classes.

Be careful, this has nothing to do with public qualifier in the inheritance list. This other public is setting the so called maximum access level, it is to say that:
  1. if you declare a derived class public-ly inheriting from another class, then all the public members of the mother class will stay public also in the daughter;
  2. if you declare a derived class protected-ly inheriting from another class, then all the public members of the mother class will be converted to protected in the daughter;
  3. if you declare a derived class private-ly inheriting from another class, then all members of the mother class will be converted to private in the daughter.
Is a daughter class inheriting everything form her mother?

The simple answer is everything of course, but to be more precise we should exclude from the list of inherited things the following members:
  • constructors
  • destructors
  • assignment operator
Even if the derived classes do not get the base class constructor, when a new instance of a derived class is created, then the default constructor (i.e. the one with no arguments) of the mother class is automatically called. The same is true when destroying. This general behavior can be overloaded specifying to the daughter class constructor (or d'cor) which base class constructor to use. See below an example:

class CMother {
 public:
   CMother(int arg1) { /* ....  */ }

   // ...

};

class CDaughter : public CMother {

 public:
   CDaughter(int arg1, int arg2) : CMother(arg1) { /* ... */ }

   // ...

};


Is it possible for a daughter class to derive from more than one mother?

Sure it is. This is called multiple inheritance and you just need to specify all the mother classes in the declaration of the daughter as a comma separated list.

For example, going back to the geometrical example above, CTriangle can also inherit from the generic class of CColoredObject in the following way:
class CTriangle : public CPolygon, public CColoredObject {
   // ...

};


A very nice example of multiple inheritance is the TH1 class in ROOT: this is inheriting from TNamed (any ROOT object having a name), from TAttLine (a line attribute), from TAttFill (a area filling attribute) and from TAttMarker (a marker attribute)

Is that all?

No, I think that the most interesting part (the inheritance evolution, it is to say: the polymorphism) is still to come. But not today... stay tuned!


Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.

0 commenti:

Posta un commento

Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.