## 1 Kopiointi- ja sijoitusmuodostimen toteuttaminen **Tehtävä:** Kurssin viimeisessä tehtävässä sinun tulee määritellä luokka Luku, sekä toteuttaa tähän kuuluvat jäsenfunktiot. Luokka sisältää yhden jäsenmuuttujan luku_, joka on osoitin kokonaislukutyypin (int) tietoon. Kun luokasta muodostetaan olio, on sen oletusmuodostimen varattava osoittimen mukainen muistialue, osoitettava varattu muisti luokan jäsenmuuttujaan ja alustettava varattu tila arvolla 0. Vastaavasti purkajan tehtävänä on vapauttaa luokan tarvitsema muisti kun luku-olio tuhotaan. Luku-luokassa on kaksi tavallista jäsenfunktiota: Tulosta() ja Muuta(). Edellinen funktio tulostaa luku-olion jäsenmuuttujan osoittaman sisällön esimerkkitulosteen mukaisesti ja jälkimmäinen muuttaa sisällön parametrina välitetyllä arvolla. Tulosta ei siis ota vastaan parametreja eikä palauta arvoa, kun taas Muuta saa kokonaislukuparametrin muttei palauta mitään. Edellisten lisäksi luokkaan on kirjoitettava kopiointi- ja sijoitusmuodostimet. Kopiomuodostimen on toimittava siten, että luku-olion kopion jäsenmuuttujan viittaama arvo on sama kuin alkuperäisellä luku-oliolla kuitenkin niin, että alkuperäinen ja kopio viittaavat eri muistialueisiin. Muistialueet sisältävät vain saman arvon. Sijoitusoperaattorin toteuttamisessa on toimittava samoin. Jos luku-olio sijoitetaan toiseen, saa sijoituksen kohde sijoitettavan luku-olion tilan mutta muutokset sijoituksen kohteena olevan olion tilassa eivät saa näkyä sijoitettavassa oliossa. Luokkaa testataan pääohjelmassa, josta siitä tehdään luku-olioita joita kopioidaan ja sijoitetaan toisiinsa. Example output: ``` Luku on: 100 Luku on: 100 Luku on: 100 Luku on: 200 Luku on: 300 Luku on: 200 ``` **Vastaus:** ``` #include using namespace std; class Luku { public: Luku(); ~Luku(); void Tulosta(); void Muuta(int luku); // Introduce copy constructor Luku(const Luku& obj); // Introduce assignment operator Luku& operator=(const Luku& obj); private: int * luku_; }; Luku::Luku() { luku_ = new int; *luku_ = 0; } Luku::~Luku() { delete luku_; } void Luku::Muuta(int luku) { *luku_ = luku; } void Luku::Tulosta() { cout << "Luku on: " << *luku_ << endl; } // Define copy constructor: perform deep copy Luku::Luku(const Luku& obj) { luku_ = new int; *luku_ = *obj.luku_; } // Define assignment operator Luku& Luku::operator=(const Luku& obj) { *luku_ = *obj.luku_; return *this; } //** Pre-defined code in the assignment **// int main() { Luku eka; eka.Muuta(100); eka.Tulosta(); // Luku on: 100 Print current value of eka Luku toka(eka); toka.Tulosta(); // Luku on: 100 copy of eka eka.Muuta(200); toka.Tulosta(); // Luku on: 100 copy of original eka, different memory address toka = eka; toka.Tulosta(); // Luku on: 200; toka gets same value than eka eka.Muuta(300); eka.Tulosta(); // Luku on: 300 // print current value of eka toka.Tulosta(); // Luku on: 200 // print current value of toka return 0; } //** ---------- ---------- ---------- **// ```