/** * Esimerkki viipaloinnista ja kloonauksesta * Miika Nurminen, 8.11.2007 * (perustuu Rintala&Jokinen, oo, luku 7.1.3) */ #include #include using namespace std; class Teos { string nimi; public: // huom. Teos- ja Kirja-luokissa kopionmuodostimen kirjoittaminen ei olisi // välttämätöntä, koska ei dynaamista sisältöä Teos(const Teos& t) : nimi(t.nimi) { kopiointi(); } Teos(string aNimi) : nimi(aNimi) { aloitus(); } virtual ~Teos() { lopetus(); } // huom. Teos- ja Kirja-luokissa sijoitusoperaattorin kirjoittaminen ei olisi // välttämätöntä, koska ei dynaamista sisältöä Teos& operator=(const Teos& t) { if (this!=&t) { sijoitus(); nimi=t.nimi; } return *this; } virtual void tulosta() { tulostaNimi(); cout << " " << nimi << endl; tulostaOmat(); // template method -suunnittelumalli } /** * dynaaminen kloonaus */ virtual Teos* kloonaa() const { return new Teos(*this); } protected: virtual void tulostaNimi() { cout << "Teos"; } virtual void tulostaOmat() {} // debug-tulostuksia varten toteutetut metodit void kopiointi() { cout << "kopioidaan "; tulostaNimi(); cout << endl; } void sijoitus() { cout << "sijoitetaan "; tulostaNimi(); cout << endl; } void aloitus() { cout << "luodaan "; tulostaNimi(); cout << endl; } void lopetus() { cout << "~"; tulostaNimi(); cout << endl; } }; class Kirja : public Teos { int painovuosi; public: Kirja(const Kirja& k) : Teos(k), painovuosi(k.painovuosi) { // yliluokan kopionmuodostimen kutsu kopiointi(); } Kirja(string aNimi, int aPainovuosi) : Teos(aNimi), painovuosi(aPainovuosi) { aloitus(); } virtual ~Kirja() { lopetus(); } virtual Kirja* kloonaa() const { return new Kirja(*this); // kutsutaan kopionmuodostinta } Kirja& operator=(const Kirja& t) { if (this!=&t) { Teos::operator =(t); sijoitus(); painovuosi=t.painovuosi; } return *this; } protected: virtual void tulostaNimi() { cout << "Kirja"; } virtual void tulostaOmat() { cout << "Painovuosi " << painovuosi << endl; } }; void tulostaTeosRef(Teos& t) { t.tulosta(); } /** * Viipaloi kirjan */ void tulostaTeos(Teos t) { t.tulosta(); } int main() { Kirja kk("C++ -ohjelmointi",2000); kk.tulosta(); tulostaTeosRef(kk); // funktiota kutsuttaessa viite toimii... tulostaTeos(kk); // ...mutta konkreettinen parametri viipaloi kopioidessa Teos t("testi"); t = kk; // kirja "viipaloituu" teokseksi sijoituksessa t.tulosta(); Teos* k2 = kk.kloonaa(); // kloonaamalla viipalointia ei tapahdu k2->tulosta(); return 0; }