...
Muodostimet
...
(Constructor)
...
Aina,
...
kun
...
luodaan
...
uusi
...
olio
...
suoritetaan
...
automaattisesti
...
muodostin-funktio.
...
Lisäksi
...
kutsutaan
...
mahdollisen
...
vanhemman
...
muodostinta,
...
sekä
...
kaikkien
...
olioiden
...
muodostimia,
...
mistä
...
luokka
...
koostuu.
...
Muodostimen
...
nimi
...
on
...
sama
...
kuin
...
luokan
...
nimi.
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 1. Parametriton muodostin.
Code Block |
---|
!Muodostimet.png|border=1! {anchor:esim1} h3. Esimerkki 1. Parametriton muodostin. {code} class CElain { public: CElain(); // Parametriton muodostin }; {code} |
Yllä
...
olevassa
...
esimerkissä
...
on
...
esitelty
...
parametriton
...
muodostin
...
(ilman
...
toteutusta).
...
Muodostimessa
...
voidaan
...
antaa
...
oliolle
...
alkuarvoja,
...
varata
...
muistia
...
jne.
...
Jos
...
muodostimelle
...
halutaan
...
antaa
...
parametreja,
...
laitetaan
...
ne
...
sulkuihin,
...
kuten
...
mihin
...
tahansa
...
funktioon.
...
Muodostin
...
ei
...
palauta
...
mitään,
...
joten
...
nimen
...
eteen
...
ei
...
saa
...
laittaa
...
mitään
...
tyyppiä,
...
ei
...
edes
...
void
...
-määrittelyä.
Anchor | ||||
---|---|---|---|---|
|
Esimerkki 2. Luokkaan CElain on lisätty muodostin, joka antaa luokan oliolle heti nimen ja massan.
Code Block |
---|
{anchor:esim2} h3. Esimerkki 2. Luokkaan CElain on lisätty muodostin, joka antaa luokan oliolle heti nimen ja massan. {code} class CElain { private: char m_Nimi[100]; float m_Massa; public: CElain(char Nimi[], float Massa); // Parametrillinen muodostin bool AsetaNimi(char Nimi[]); // Asetusfunktio char[] PalautaNimi(); // Palautusfunktio bool AsetaMassa(float Massa); // Asetusfunktio float PalautaMassa(); // Palautusfunktio }; {code} |
Muodostimelle
...
täytyy
...
tehdä
...
vielä
...
toteutus,
...
joka
...
voi
...
olla
...
esim.
...
seuraavanlainen:
Code Block |
---|
} CElain::CElain(char Nimi[], float Massa) // Parametrillinen muodostin { strcpy(m_Nimi, Nimi); m_Massa = Massa; } {code} |
Luokalla
...
on
...
aina
...
oletusmuodostin,
...
esim
...
CElain::CElain(),
...
mutta
...
jos
...
ohjelmoija
...
tekee
...
yhdenkin
...
oman
...
muodostimen
...
ei
...
oletusmuodostinta
...
voida
...
enää
...
käyttää.
...
Yllä
...
olevassa
...
esimerkissä
...
tulisi
...
kaikki
...
CElain-luokan
...
oliot
...
muodostaa
...
antamalla
...
niille
...
nimi
...
ja
...
massa.
...
Esimerkiksi:
Code Block |
---|
} CElain kissa("misu", 5.2); {code} |
Mutta
...
koska
...
oletusmuodostinta
...
ei
...
voida
...
enää
...
käyttää,
...
seuraava
...
ei
...
ole
...
validia
...
koodia:
Code Block |
---|
} CElain kissa; {code} |
Note |
---|
Jos parametritonta muodostinta halutaan käyttää, tulee myös se lisätä luokkaan: |
Code Block |
---|
{note}Jos parametritonta muodostinta halutaan käyttää, tulee myös se lisätä luokkaan:{note} {code} class CElain { ... public: CElain(); // Parametriton muodostin CElain(char Nimi[], float Massa); // Parametrillinen muodostin ... {code} h2. Kopiomuodostimet |
Kopiomuodostimet (Copy
...
Constructor)
...
Kopiomuodostin
...
on
...
muodostin,
...
jolle
...
annetaan
...
parametrina
...
referenssi
...
itsensä
...
tyyppiseen
...
olioon.
...
Kopiomuodostimen
...
idea
...
on
...
mahdollistaa
...
olion
...
monistaminen
...
eli
...
kopioiminen.
...
C+
...
+
...
tarjoaa
...
oletuskopiomuodostimen
...
joka
...
osaa
...
tehdä
...
matalan
...
kopioinnin
...
(shallow
...
copy),
...
tarkoittaen
...
että
...
se
...
kopioi
...
kaikkien
...
jäsenmuuttujien
...
arvot,
...
myös
...
osoittimien,
...
mikä
...
on
...
ongelma,
...
kts.
...
Esimerkki
...
2.
...
Esimerkki
...
3.
...
Kopiomuodostimen
...
esittely.
Code Block |
---|
} class CElain { private: float m_Massa; public: CElain() {} // Tyhjä oletusmuodostin. CElain(const CElain&); // Kopiomuodostin }; {code} |
Yllä
...
olevassa
...
esimerkissä
...
on
...
esitelty
...
kopiomuodostin
...
(ilman
...
toteutusta).
...
Toteutus
...
voisi
...
olla
...
seuraavanlainen:
Code Block |
---|
} CElain::CElain(const CElain& Instanssi) { this->m_Massa = Instanssi.m_Massa; // Kopioidaan annetun olion muuttujan m_Massa arvo omaamme. } {code} |
Yllä
...
annettu
...
toteutus
...
on
...
itse
...
asiassa
...
sama
...
kuin
...
oletuskopiomuodostin.
...
Se
...
kopioi
...
kaikkien
...
jäsenmuuttujien
...
arvot.
...
Esimerkki
...
4.
...
Kopiomuodostin,
...
kun
...
luokassa
...
on
...
osoittimia.
Code Block |
---|
} class CElain { private: float m_Massa; char* m_Nimi; // Osoitin. public: CElain(char Nimi[]) { m_Nimi = new char[strlen(Nimi) + 1]; // Varataan muistia, annetun merkkijonon verran. } ~CElain() { delete [] m_Nimi; // Vapautetaan varattu muisti. } CElain() { } CElain(const CElain& Instanssi) { this->m_Massa = Instanssi.m_Massa; this->m_Nimi = Instanssi.m_Nimi; // Tässä kopioidaan ainoastaan osoittimen arvo, ei itse muistia! } }; {code} |
Yllä
...
oleva
...
kopiomuodostin
...
(joka
...
siis
...
on
...
kuten
...
oletuskopiomuodostin)
...
aiheuttaa
...
ongelmia.
...
Ajatellaan
...
seuraavaa
...
tilannetta:
...
- Luodaan
...
- ensimmäinen
...
- olio,
...
- sille
...
- annetaan
...
- nimi
...
- ja
...
- varataan
...
- muodostimessa
...
- tarvittavan
...
- määrän
...
- muistia
...
- nimeä
...
- varten.
...
- Luodaan
...
- toinen
...
- olio,
...
- käyttämällä
...
- kopiomuodostinta,
...
- antamalla
...
- ensimmäinen
...
- olio
...
- parametrina.
...
- Nyt
...
- molemmat
...
- oliot
...
- omaavat
...
- saman
...
- massan
...
- ARVON
...
- ja
...
- saman
...
- osoittimen
...
- ARVON
...
- muistiin,
...
- jossa
...
- sijaitsee
...
- nimi.
...
- Siis
...
- molemmat
...
- oliot
...
- osoittavat
...
- samaan
...
- muistialueeseen.
...
- Tuhotaan
...
- ensimmäinen
...
- olio,
...
- jolloin
...
- kutsutaan
...
- sen
...
- hajoitin,
...
- joka
...
- vapauttaa
...
- varatun
...
- muistin.
...
- Nyt
...
- meillä
...
- on
...
- enään
...
- toisena
...
- luoto
...
- olio,
...
- jonka
...
- m_Nimi
...
- osoittaa
...
- muistiin,
...
- joka
...
- juuri
...
- vapautettiin
...
- !
...
- -->
...
- Meillä
...
- on
...
- katastrofi
...
- käsissä
...
- !
...
Yllä
...
kuvatun
...
ongelman
...
välttämiseksi
...
voimme
...
kirjoittaa
...
oman
...
kopiomuodostimen,
...
jossa
...
suoritetaan
...
syvä
...
kopiointi
...
(deep
...
copy),
...
eli
...
varataan
...
tarvittava
...
muisti
...
ja
...
kopioidaan
...
merkkijono
...
sinne:
Code Block |
---|
} class CElain { ... CElain(CElain& Instanssi) { this->m_Massa = Instanssi.m_Massa; this->m_Nimi = new char[strlen(Instanssi.m_Nimi) + 1]; // Varataan tarvittava muisti merkkijonolle. strcpy(this->m_Nimi, Instanssi.m_Nimi); // Tässä kopioidaan merkkijono. } }; {code} |
Tämä
...
kopiomuodostin
...
kopioi
...
osoittimen
...
sisältämän
...
muistin
...
oikein.
...
Nyt
...
voidaan
...
muodostaa
...
haluttu
...
määrä
...
kopioita
...
ja
...
ne
...
käyttäytyvät
...
kuten
...
pitääkin.