Pino
Lifo-pino on tietorakenne, johon voidaan tallentaa tietoa siten,
että viimeksi talletettu tieto tulee ensimmäisenä pois.
Esimerkki 1. Pinon luokkamalli ja toteutus, sekä käyttöesimerkki
main():sta.
#include <iostream>
using namespace std;
// Pino, johon voi tallettaa kokonaislukuja
class CPino
// Stack, LIFO=Last In First Out
{
private:
int m_PinonJasenet[100];
int m_PinonHuippu;
public:
CPino(const int Huippu=0)
{
m_PinonHuippu = Huippu;
}
void LisaaUusiPinoon(const int Uusi)
{
m_PinonJasenet[m_PinonHuippu] = Uusi;
m_PinonHuippu++;
// näyttää ensimmäiseen tyhjään paikkaan.
assert(m_PinonHuippu < 100);
// Testaa että pinon huippu varmasti alle sata.
}
int OtaPinosta()
{
m_PinonHuippu--;
assert(m_PinonHuippu >= 0);
// Testaa että pinon huippu varmasti yli nollan.
return m_PinonJasenet[m_PinonHuippu];
}
int NaytaMaaraPinossa() const
{
return m_PinonHuippu;
}
void NaytaKokoPino() const
{
for (int i=0; i<m_PinonHuippu; i++) {
cout << "#" << i << ": " << m_PinonJasenet[i] << endl;
}
cout << "Pinon huippu on #" << m_PinonHuippu << endl;
}
};
int main()
{
CPino pino;
pino.LisaaUusiPinoon(-4);
pino.LisaaUusiPinoon(1234);
pino.NaytaKokoPino();
cout << "Pinosta otettu luku: " << pino.OtaPinosta() <<
endl;
pino.NaytaKokoPino();
}
Mallit (Template)
Malleja pidetään vaikeana C++-kielen ominaisuutena. Tämä pitää vain
osin paikkansa. Mallit ovat oikein käytettynä erittäin tehokas
ohjelmoijan apukeino.
Mallit ovat luokan abstraktio, eli malleilla kuvataan millaisia
luokkia malleista voidaan luoda. Näistä luokista sitten luodaan
olioita, normaaliin tapaan. Mallit voivat parametrisoida kokonaislukuja
sekä tietotyyppejä (sisäänrakennettuja sekä itse tehtyjä luokkia).
Malleja voi olla sekä luokka-, että funktiomalleja.
Esimerkki 1. Funktiomalli, jossa tietotyyppi on parametrisoitu.
template <typename T>
T Kerro(
T a,
T b)
{
return a*b;
// Palauttaa annettujen lukujen tulon.
}
Käyttö:
int tulos1 = Kerro
<int>(1, 3);
// int kertominen
float tulos2 = Kerro
<float>(1.34, 3.14);
// float kertominen
Esimerkissä luotiin funktiomalli, joka kertoo kaksi lukua yhteen ja
palauttaa tuloksen. Käyttö tapahtuu määrittämällä minkä tietotyypin
Kerro-funktio halutaan luoda.
HUOM
<tietotyyppi> ei välttämätön, jos kääntäjä osaa itse päätellä
tietotyypin. Tässä esimerkissä
<int> määritettä ei tarvita, sillä parametreiksi annetaan vain
int-tyyppisiä arvoja.
Esimerkki 2. Luokkamalli, jossa tietotyyppi on parametrisoitu.
template <typename T>
class CLuokka
{
private:
T m_Muuttuja;
public:
void AsetaMuuttuja(const
T);
T PalautaMuuttuja() const;
};
Käyttö:
int main()
{
CLuokka
<int> int_luokka;
int_luokka.AsetaMuuttuja(34);
CLuokka
<float> float_luokka;
float_luokka.AsetaMuuttuja(3.14576);
}
Tässä esimerkissä esitellään luokkamalli, jonka tietotyyppi on
parametrisoitu. Käyttö tapahtuu antamalla tietotyyppi hakasulkujen
sisällä heti luokan nimen jälkeen. Käyttö-kohdassa luodaan
CLuokka<int> ja
CLuokka<float> luokat. Tämä tarkoittaa että, CLuokka-luokan
jäsenmuuttuja
m_Muuttuja on ensimmäisessä tapauksessa
int ja toisessa
float.
Mallien ongelmia
Se miksi malleja pidetään vaikeana on niiden hieman omituinen
syntaksi ja se, että ne tuottavat käsittämättömiä virheilmoituksia.
Mallien etuja
Etuna mallien käytössä on se, että ne voivat säästää saman asian
useaan otteeseen kirjoittamiselta. Jos sinulla on esimerkiksi
TulostaBinaari()-funktio, joka tulostaa minkä tahansa muuttujan
binäärimuodossa ruudulle. Ilman malleja joutuisit ylikuormittamaan
funktion jokaiselle sisäiselle tietotyypille (int, char, float, jne.)
ja sen lisäksi
jokaiselle itse tekemällesi luokalle/tietorakenteelle.
Mallien avulla kirjoitat koodin
yhteen kertaan ja tämä koodi toimii kaikille tietotyypeille ja lisäksi
omille luokille.
Esimerkki 3. TulostaBinaari()-funktion toteutus mallien avulla.
template <typename T>
void TulostaBinaari(T arvo)
{
for (int i=sizeof(T)-1; i>=0; i--) {
for (int j=8-1; j>=0; j--) {
cout << ((arvo >> (i+j)) & 1);
}
}
}
Käyttö:
int main()
{
TulostaBinaari<char>(34); cout << endl;
TulostaBinaari<int>(342623); cout << endl;
TulostaBinaari<float>(3.1475); cout << endl;
}