Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

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.