Prev Next Up Title Contents Index

Miksi luokkamallia tarvitaan?


Tarkastellaan aluksi seuraavaa ongelmaa: halutaan tehdä luokka list, johon voidaan tallettaa yksittäisiä kirjaimia. Yksinkertaisuuden vuoksi luokka toteutetaan seuraavassa taulukon avulla, mutta luokan ulkoinen käyttö ei muutu yhtään luokan sisäisen toteutuksen muuttuessa. Jotta cList-luokan alkioiden tyyppi olisi helppo muuttaa, on tyyppi esitelty #define:n avulla

listtarr.cpp - lista taulukon avulla

	/*  LISTARR.CPP
	
	Esimerkki (yksisuuntaisen) listan toteuttamisesta taulukon avulla.
	Kaksi esimerkkiä mahdollisuuksista käydä lista kokonaan läpi.
	  joko: for (c=l.first(); !l.out(); c=l.next() )  -> käytä c ??
	  tai:  for (l.tobegin(); !l.out(); l.forward() ) -> käytä l.current()
	Ei tapahdu "vahinkoa", vaikka listaa yritetään käyttää liian pitkälle.
	
	vl 6.11.1993
	
	Tehtäviä 1) Peri luokasta luokka cList2, joka on kaksisuuntainen ja
	            jossa voidaan siis liikkua kumpaankin suuntaan.
	
	         2) Toteuta list "oikeana" dynaamisena listana.
	
	         3) Peri tehtävän 2 listasta 2-suuntainen lista.
	            Onnistuuko kunnolla?
	
	         4) Mitä tässä pitää muuttaa, mikäli halutaan käyttää
	            muun tyyppisiä listan alkioita?
	            Kokeile reaalilukuja ja piste-luokan alkioita!
	            (Piste-luokka ks. MYSTREAM.CPP)
	
	         5) Entä jos halutaan käyttää samassa ohjelmassa kahta
	            tai useampaa eri listaan menevää tyyppiä?
	*/
	
	#include <iostream.h>
	
	inline int inside(int a,int x,int b) // x välille [a,b], jos b<a niin a
	  { return b < a ? a : x < a ? a : x < b ? x : b; }
	
	#define MAX_ELEM 100
	
	#define TYPE char
	
	class cList {
	protected:
	  int nelem;           // Alkioiden lukumäärä
	  TYPE data[MAX_ELEM]; // Alkioden taulukko
	  int cursor;          // Sijainti listassa
	public:
	  cList()                { nelem = 0; tobegin();                     }
	  ~cList()               { nelem = 0;                                }
	
	  int  out()       const { return ( cursor < 0 || nelem <= cursor ); }
	  int  tobegin()         { cursor = 0;       return out();           }
	  int  forward()         { ++cursor;         return out();           }
	  int  toend()           { cursor = nelem-1; return out();           }
	  TYPE current()   const { return data[inside(0,cursor,nelem-1)];    }
	  TYPE first()           { tobegin(); return current();              }
	  TYPE next()            { forward(); return current();              }
	  TYPE last()            { toend();   return current();              }
	  int  empty()     const { return ( nelem == 0 );                    }
	  int  add(TYPE p)       { if ( nelem >= MAX_ELEM ) return 1;
	                           data[nelem++] = p; return 0;
	                         }
	}; /* cList */
	
	
	#define VIIVA "------------------------------------------------------------\n"
	/****************************************************************************/
	int main(void)
	{
	  cout << VIIVA;
	
	  cList lc; lc.add('a'); lc.add('b'); lc.add('c'); lc.add('d');
	
	  for (char c=lc.first(); !lc.out(); c=lc.next() )
	    cout << c << " ";
	
	  cout << c << "\n" << VIIVA;
	
	  for (lc.tobegin(); !lc.out(); lc.forward() )
	    cout << lc.current() << " ";
	
	  cout << lc.current() << "\n" << VIIVA;
	
	  return 0;
	}
Luokka toimii varsin hyvin, kunnes tulee tarve käyttää yhtäaikaa listaa esimerkiksi sekä kirjaimille, että reaaliluvuille. Huomattakoon, että luokassa on tarjottu valmiit funktiot listan kaikkien alkioiden läpikäymiseksi.

Tehtävä 1.34 Lineaarinen lista

Tee ohjelman LISTARR.CPP tehtävät.


Prev Next Up Title Contents Index