...
Hajoittimen nimi on muotoa mato(~) ja sen perään luokan nimi, esim. ~CElain().
Hajoittimen ominaisuuksia:
- Hajoittimessa tulee vapauttaa muodostimessa varatut muistit.
- Kutsutaan automaattisesti, kuten muodostintakin.
- Hajoittimelle ei voi antaa parametreja.
- Vaikka muodostin on ylikirjoitettu, voidaan silti käyttää oletushajoitinta.
Kopiomuodostimet (Copy Constructor)
...
Esimerkki
...
1
...
. Yksinkertainen hajoitin
Code Block |
---|
class CElain { private: float m_Massa; public: CElain() {} // Tyhjä oletusmuodostin. CElain(const CElain&~CElain(); // KopiomuodostinHajoitin }; |
Yllä olevassa esimerkissä on esitelty kopiomuodostin (ilman toteutusta). Toteutus voisi olla seuraavanlainenHajoittimen toteutus:
Code Block |
---|
CElain::CElain(const CElain& Instanssi) {
this->m_Massa = Instanssi.m_Massa; // Kopioidaan annetun olion muuttujan m_Massa arvo omaamme.
}
|
Yllä annettu toteutus on itse asiassa sama kuin oletuskopiomuodostin. Se kopioi kaikkien jäsenmuuttujien arvot.
Esimerkki 2: 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! } }; |
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.
}
};
|
...
Tänne koodit
}
|
Hajoittimen ominaisuuksia:
- Hajoittimessa tulee vapauttaa muodostimessa varatut muistit.
- Kutsutaan automaattisesti, kuten muodostintakin.
- Hajoittimelle ei voi antaa parametreja.
- Vaikka muodostin on ylikirjoitettu, voidaan silti käyttää oletushajoitinta.