Prev Next Up Title Contents Index

Olioiden sijoittaminen

Olioiden sijoittaminen toisiinsa tapahtuu oletuksena muistikopiona. Esimerkiksi edellisessä esimerkissä ftulosta aliohjelman kutsussa on luotu tilapäinen cJono- tyyppinen olio (olkoon vaikkapa nimellä temp), jolle on sijoitettu tulostettava olio j1:

Click here for Picture 

Kuva . Olion käyttäytyminen ilman kopiointikonstruktoria

Siis aliohjelman aikana kumpikin olio (j1 ja temp) osoittivat samaan merkkijonoon. Kun aliohjelmasta poistuttiin ja kutsuttiin jonon hävittäjää, vapautettiin tietenkin temp -olion osoittama jono, joka onnettomuudeksi olikin sama kuin j1 -olion osoittama jono! Tämä on aliasing-ongelma

Vielä huonommin kävisi, jos edellisen mallin pääohjelmassa olisi koodi:

	{
	  cJono j1("j1");
	  {
	     cJono j2("Kissa");
	     j2 = j1;    // j2:en Kissa häviäisi kuin p...
	     j2.tulosta();
	  }
	  j1.tulosta();  // j1:en jono jo vapautettu!!
	...
	}

Tällöin j1:en jono vapautettaisiin ja j2:en alunperin osoittama jono jäisi ilman osoitinta ja jäisi näin ollen kellumaan muistiin:

Click here for Picture 

Kuva . Olion sijoittaminen

Aliohjelman parametrin välittämisongelma voidaan korjata referensseillä kuten edellä sanottiin tai sitten kirjoittamalla luokalle yksi rakentaja lisää: kopiointimuodostaja (copy constructor, parametrina olion tyyppi), jota kutsutaan parametrin välityksen yhteydessä:

copycons.cpp - sijoitus ja kopiointi tehtävä itse

	/* COPYCONS.CPP - copy constructor */
	...
	  cJono(const cJono &j) {
	    max_pit = j.max_pit;
	    s = new char[max_pit+1];
	    strcpy(s,j.s);
	    printf("Copy constructor: "); tulosta(); // Testejä varten!
	  }
Näin korvataan oletus kopiointimuodostaja (default copy constructor), joka tekisi vain binäärisen sijoituksen. Kopiointimuodostaja on muodostaja, jolla on parametrinaan saman luokan olio tai viite saman luokan olioon.

Sijoitusongelma ei ratkea tälläkään, vaan joudutaan määrittelemään sijoitus uudelleen:

	/* COPYCONS.CPP - copy constructor */
	...
	  cJono &operator=(const cJono &j) {
	    if ( &j == this ) return *this; // Jos yritetään sijoittaa its.
	    if ( max_pit < j.max_pit ) {   // Jollei mahdu niin uusi tila
	      if ( max_pit ) delete [] s;
	      s = new char[j.max_pit+1];
	      max_pit = j.max_pit;
	    }
	    strcpy(s,j.s);
	    return *this;
	  }

Huomattakoon, että turvallisuussyistä on tarkistettava, ettei arvoa sijoiteta oliolle itselleen (vrt. aliasing)! Lisäksi on syytä palauttaa sijoituksen tulos, jotta seuraava ketju olisi mahdollinen:

	j3 = j2 = j1;
Sijoitusoperaattoria kutsutaan sijoituksissa ja kopiointimuodostajaa aliohjelmien arvoparametrikutsuissa ja funktion arvon palautuksessa.

Huomautus! Sijoitusoperaattori ei periydy!


Prev Next Up Title Contents Index