Objektorienterad Programkonstruktion

2D1947 Objektorienterad Programkonstruktion

Ledningar och tips för laboration 7 (bankomaten)

Många undrar vad atm_create_parts egentligen är för mystisk funktion. Ni kan tänka på atm_create_parts som ert main. Den anropas i själva verket i slutet av main, som i princip ser ut så här:
int main()
{
    // Skapa en kommunikationskanal till fönstersystemet.

    // Skapa ATM-instansen som ska skickas som argument till atm_create_parts.
    // Detta objekt kommer bl a att skapa bankomatens fönster på skärmen.

    // Anropa atm_create_parts

    // Event loop: Vänta och reagera på händelser från fönstersystemet, t ex
    // knapptryckningar, musförflyttningar etc.

    return 0;
}

Varför måste bankomatens delar skapas i atm_create_parts? Anledningen är att kommunikationskanalen med fönstersystemet måste skapas innan delarna kan rita upp sig själva. Alltså kan man inte låta bankomatdelarna vara globala eftersom deras konstruktörer då skulle köras innan main anropats.

Vaför måste man överhuvudtaget instansiera bankomatens delar själv? Eftersom ni skapar nya subklasser (för att kunna omdefiniera delarnas virtuella funktioner och eventuellt lägga till ytterligare datamedlemmar) måste ni också instansera dem själva. Om delarna ATMCardReader etc inte hade behövt subklassas hade de lika gärna kunnat vara datamedlemmar i klassen ATM.

Varför måste bankomatdelarna deklareras static i atm_create_parts? De kan inte vara vanliga automatiska, lokala variabler eftersom de skulle försvinna då atm_create_parts returnerar till main. Man kan dock använda new istället om man vill, t ex

Door* door_pointer; // global pekarvariabel
// ...

void atm_create_parts(ATM& atm)
{
    door_pointer = new Door(atm);
    // ...
}
I detta fall är door_pointer en global pekare till en instans av din subklass Door.

Accessfunktionerna i ATM (se hardware.hh) returnerar referenser till de delar du har instansierat. Om du t ex har skrivit

static Door my_door(atm);
i atm_create_parts kommer atm.door() att returnera en referens till my_door.

Om du inför helt nya hjälpklasser finns det naturligvis inga accessfunktioner för dessa delar i ATM. Hur kommer man då åt dem? Det finns flera sätt. Man kan skicka med referenser eller pekare till dem som argument till de andra objektens konstruktörer (du bestämmer ju själv vilka argument subklassernas konstruktörer ska ha). Man kan skapa ett sammanhållande objekt som innehåller de andra objekten som datamedlemmar. Man kan också använda globala pekare till bankomatdelarna, t ex door_pointer ovan.

Kan man då inte skapa en subklass till ATM som innehåller t ex extra accessfunktioner eller datamedlemmar? Ja och nej. Naturligtvis kan man härleda en ny subklass från ATM, liksom från vilken annan klass som helst. Problemet är dock att ATM-instansen redan är skapad när atm_create_parts anropas, och det går inte att påverka dess klasstillhörighet i efterhand.


harald@nada.kth.se