Opdracht 3: Inheritance en Polymorphisme.

© Harry Broeders.

Deze opdracht bestaat uit de deelopdrachten 3a t/m 3c. Alle deelopdrachten moet je laten aftekenen door de docent.

In een bedrijf werken verschillende soorten werknemers:

Binnen de salarisadministratie van het bedrijf heeft elke werknemer een registratienummer.

De analist die de specificaties voor het salarisadministratie programma heeft opgesteld heeft bedacht dat er rekening mee moet worden gehouden dat er in de toekomst andere soorten werknemers moeten worden toegevoegd. Bijvoorbeeld stukwerkers die werken voor een vast stukprijs. Het programma moet dus zoveel mogelijk onafhankelijk van het concrete werknemer type gemaakt worden.

Hieronder volgt een voorbeeld van een functie die onafhankelijk van het werknemer type is:

void printMaandSalaris(const Werknemer& w) {
   cout<<"Werknemer: "<<w.geefNummer()
       <<" verdient: "<<setw(8)<<setprecision(2)<<fixed
       <<w.geefSalaris()<<" Euro."<<endl;
}

Deze functie wordt vanuit de functie main als volgt aangeroepen (werk1.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02.):

int main() {
   FreeLancer f(1, 25.75);    // werknemer 1 verdient 25.75 per uur
   VasteKracht v(2, 1873.53); // werknemer 2 verdient 1873.53 per maand

   f.werkUren(84);            // werknemer 1 werkt (deze maand) 84 uren

   cout<<"Maand 1:"<<endl;
   printMaandSalaris(f);
   printMaandSalaris(v);

   f.werkUren(13.5);          // werknemer 1 werkt (deze maand) 13.5 uren

   cout<<"Maand 2:"<<endl;
   printMaandSalaris(f);
   printMaandSalaris(v);

   cin.get();
   return 0;
}

Denk er aan hoe een blaft! Bestudeer indien nodig hoofdstuk 4 uit het dictaat. De relatie tussen de verschillende classes is hiernaast gegeven.

-

Opdracht 3a.

Implementeer de drie benodigde classes: Werknemer, FreeLancer en VasteKracht zodat het bovenstaande hoofdprogramma uitgevoerd kan worden. Denk aan het correct gebruik van const. In les 18 zul je leren dat je in de class Werknemer een virtuele destructor moet definiëren maar dat mag je nu nog even vergeten.

De juiste uitvoer is:
Maand 1:
Werknemer: 1 verdient: 2163.00 Euro.
Werknemer: 2 verdient: 1873.53 Euro.
Maand 2:
Werknemer: 1 verdient: 347.631 Euro.
Werknemer: 2 verdient: 1873.53 Euro.

1 : Het antwoord kan ook 346.62 zijn. Het juiste antwoord is 13.5 * 25.75 = 347.625. Je zou misschien verwachten dat deze uitkomst door het gebruik van setprecision(2) netjes afgerond wordt. setprecision(2)rond inderdaad netjes af op 2 cijfers achter de decimale punt maar, als door een klein afrondfoutje in de berekenig, het resultaat 347.624999999999999999.... is dan wordt deze waarde (netjes) naar beneden afgerond. Het gebruik van floating point getallen is altijd lastig. Zie hier voor meer info: double.htm. Als je echt alles wilt weten lees dan: "What Every Computer Scientist Should Know About Floating-Point Arithmetic".

Merk op dat de functie printMaandSalaris niet "weet" welk soort Werknemer gebruikt wordt. Dit betekent dat deze polymorphic functie voor alle huidige "soorten" werknemers te gebruiken is. De functie is zelf ook voor toekomstige "soorten" werknemers bruikbaar. Dit maakt het programma eenvoudig uitbreidbaar. Op dit moment is het nodig om het programma uit te breiden met een nieuw "soort" werknemer. Deze stukwerker werkt voor een vast stukprijs.

De main functie wordt nu als volgt uitgebreid (werk2.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02.):

int main() {
   FreeLancer f(1, 25.75);    // werknemer 1 verdient 25.75 per uur
   VasteKracht v(2, 1873.53); // werknemer 2 verdient 1873.53 per maand
   StukWerker s(3, 1.05);     // werknemer 3 verdient 1.05 per stuk

   f.werkUren(84);            // werknemer 1 werkt (deze maand) 84 uren
   s.produceerStuks(1687);    // werknemer 3 produceert (deze maand) 1687 stuks

   cout<<"Maand 1:"<<endl;
   printMaandSalaris(f);
   printMaandSalaris(v);
   printMaandSalaris(s);

   f.werkUren(13.5);          // werknemer 1 werkt (deze maand) 13.5 uren
   s.produceerStuks(0);       // werknemer 3 produceert (deze maand) 0 stuks

   cout<<"Maand 2:"<<endl;
   printMaandSalaris(f);
   printMaandSalaris(v);
   printMaandSalaris(s);

   cin.get();
   return 0;
}

Opdracht 3b.

Implementeer de benodigde class StukWerker zodat het bovenstaande hoofdprogramma uitgevoerd kan worden.

De juiste uitvoer is:
Maand 1:
Werknemer: 1 verdient: 2163.00 Euro.
Werknemer: 2 verdient: 1873.53 Euro.
Werknemer: 3 verdient: 1771.35 Euro.
Maand 2:
Werknemer: 1 verdient: 347.63 Euro.
Werknemer: 2 verdient: 1873.53 Euro.
Werknemer: 3 verdient: 0.00 Euro.

Er is nog een "soort" werknemer waarmee we het programma kunnen uitbreiden. Een manager is een werknemer die andere werknemers leiding geeft. De meeste managers hebben zelf ook weer een manager boven zich. Het bedrijf dat we als voorbeeld nemen heeft een orginele manier bedacht om het salaris van een manager te bepalen. Het salaris van de manager is 2 maal zo hoog als het gemiddelde salaris van de mensen waaraan deze manager direct leiding geeft.

Het programma moet natuurlijk ook het salaris van managers kunnen berekenen. De relatie tussen manager en werknemer is als volgt:

De relatie tussen de classes Werknemer, VasteKracht en Manager is hiernaast gegeven.

Het hoofdprogramma wordt nu (werk3.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02.):

int main() {
   StukWerker s(1, 1.05);     // werknemer 1 verdient 1.05 per stuk
   FreeLancer f(2, 25.75);    // werknemer 2 verdient 25.75 per uur
   VasteKracht v1(3, 1873.53);// werknemer 3 verdient 1873.53 per maand

   Manager m1(4);             // werknemer 4 is de manager van:
   m1.geeftLeidingAan(s);     // -  werknemer 1
   m1.geeftLeidingAan(f);     // -  werknemer 2
   m1.geeftLeidingAan(v1);    // -  werknemer 3

   VasteKracht v2(5, 2036.18);// werknemer 5 verdient 2036,18 per maand
   Manager m2(6);             // werknemer 6 is de manager van:
   m2.geeftLeidingAan(v2);    // -  werknemer 5
   m2.geeftLeidingAan(m1);    // -  werknemer 4

   s.produceerStuks(678);     // werknemer 1 produceert 678 stuks
   f.werkUren(84);            // werknemer 2 werkt 84 uren

   printMaandSalaris(s);
   printMaandSalaris(f);
   printMaandSalaris(v1);
   printMaandSalaris(m1);
   printMaandSalaris(v2);
   printMaandSalaris(m2);

   cin.get();
   return 0;
}

Opdracht 3c.

Implementeer de benodigde class Manager zodat het bovenstaande hoofdprogramma uitgevoerd kan worden. Maak bij de implementatie van een Manager gebruik van een std::vector met pointers naar Werknemer's.

De juiste uitvoer is:
Werknemer: 1 verdient: 711.90 Euro.
Werknemer: 2 verdient: 2163.00 Euro.
Werknemer: 3 verdient: 1873.53 Euro.
Werknemer: 4 verdient: 3165.62 Euro.
Werknemer: 5 verdient: 2036.18 Euro.
Werknemer: 6 verdient: 5201.80 Euro.

verder met opdracht 4 ...