Prev Next Up Title Contents Index

Luokkamalli (class template)


Yleiskäyttöisyysongelma ratkaistaan esittelemällä cList-luokka luokkamallin(muotti) avulla:

listtemp.cpp - lista luokkamallin avulla

	/*  LISTTEMP.CPP
	...
	Tehtäviä 1) Peri luokasta luokka cList2, joka on kaksisuuntainen ja
	            jossa voidaan siis liikkua kumpaankin suuntaan.
	
	         2) Toteuta cList "oikeana" dynaamisena listana.
	
	         3) Peri tehtävän 2 listasta 2-suuntainen lista.
	            Onnistuuko kunnolla?
	
	         4) Jäsenfunktiot first,last ja next ovat oikeastaan
	            tarpeettomia, koska sama ominaisuus saadaan aikaan
	            tobegin, toend, forward ja current -funktioiden avulla.
	            Kuitenkin joskus tarvitaan ainakin kahta toisistaan
	            riippumattomasti listaa käsittelevää "iteraattoria".
	            Esitä ratkaisuehdotus, jolla lista voidaan samanaikaisesti
	            tulostaa sekä alusta että lopusta päin, eli esim lista 1 2 3
	            tulostuisi: 1 3 2 2 3 1
	*/
	...
	template <class TYPE>
	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)];    }
	...
	}; /* cList */
	...
	
	int main(void)
	{
	...
	  cList<char> 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 << " ";
	...
	  cList<double> ld; ld.add(1.2); ld.add(20.3); ld.add(300.4); ld.add(400.5);
	  for (double d=ld.first(); !ld.out(); d=ld.next() )  cout << d << " ";
	...
	  cList<cPiste> lp; lp.add(cPiste(1,1)); lp.add(cPiste(2,4));
	  for (cPiste p=lp.first(); !lp.out(); p=lp.next() )  cout << p << " ";
	...
	  cList<int> li; li.add(1); li.add(2); li.add(3);
	  for (li.tobegin(); !li.out(); li.forward() )  cout << li.current() << " ";
	...
	}
Template toimii siis lähes kuten #define. Luokasta monistuu eri versio kutakin tyyppiä kohti (generoitu luokka = template class). Jos monistuminen haluttaisiin välttää, pitäisi luokasta tehdä void -osoittimia käsittelevä versio. Tällöinkin kannattaa template:lla tehdä apuluokat tyypinmuunnoksia varten.

Template on voimassa vain luokan määrittelyn lopettavaan puolipisteeseen. Mikäli esimerkiksi funktio add haluttaisiin tehdä ei-inline-funktiona, pitäisi template aloittaa uudelleen jokaista funktiota kohden:

listtem2.cpp - lista luokkamallin avulla, ei-inline funktio

	...
	template <class TYPE>
	int  cList<TYPE>::empty() const {
	  return ( nelem == 0 );
	}
	
	template <class TYPE>
	int  cList<TYPE>::add(TYPE p)
	{
	  if ( nelem >= MAX_ELEM ) return 1;
	  data[nelem++] = p;
	  return 0;
	}

Tehtävä 1.35 Template ja luokat

Tee ohjelman LISTTEMP.CPP tehtävät.


Prev Next Up Title Contents Index