Olio-ohjelmointi

Tässä harjoituksessa kerrataan mitä tarkoittavat termit muistiosoite ja osoitin l. pointteri. Lisäksi tutustutaan uuteen käsitteeseen referenssi l. viittaus .

C++-ohjelmoinnissa referenssi on viittaus olemassa olevaan muuttujaan. Se toimii aliaksena, eli referenssi ja alkuperäinen muuttuja viittaavat samaan muistipaikkaan. Referenssi määritellään käyttämällä &-operaattoria. Referensseillä on seuraavat ominaisuudet:

  • Ne on sidottava alustuksen yhteydessä, eikä niitä voi vaihtaa viittaamaan toiseen muuttujaan myöhemmin.
  • Käyttämällä referenssiä voidaan välttää kopioimasta suuria tietorakenteita funktioiden parametreissa.
  • Kaikki muutokset referenssin kautta vaikuttavat alkuperäiseen muuttujaan.
Esimerkki:
 
    int a = 10; 
    int &ref = a; // ref on viittaus muuttujaan a 
    ref = 20; // nyt myös a: arvo on 20 

    int *pointer=&a;
    *pointer=30; // nyt myös a:n arvo on 30
Referenssejä käytetään usein funktioiden parametreina ja palautusarvoina tehokkuuden parantamiseksi.

Harjoitus5

HUOM! Luo kullekin luokalle erillinen h-tiedosto ja cpp-tiedosto.

Luo C++-projekti nimeltään h5

Osoitin

  1. Luo mainissa int muuttuja a ja anna arvoksi 5
  2. Tulosta muuttujan a arvo ja osoite, jolloin tuloksena tulisi olla jotain tällaista:
    a:n arvo on: 5 ja osoite on: 0x5449fff84c
    

  3. Lisää osoitinmuuttuja pointerA ja sijoita siihen muuttujan a osoite ja
    • Tulosta osoittimen osoittaman muistipaikan osoite
    • Tulosta osoittimen osoittaman muistipaikan sisältö
    Nyt tuloksena pitäisi olla jotain tällaista:
    Pointterin osoittama osoite on: 0x5449fff84c
    Pointterin osoittaman muistipaikan arvo on: 5
    


Referenssi

  1. Luo referenssi nimeltään refA ja laita se viittaamaan muuttujaan a ja
    • Tulosta refA:n osoittama osoite
    • Tulosta refA:n osoittaman muistipaikan sisältö
  2. Suorita sovellus jolloin tuloksena pitäisi olla jotain tällaista:
      refA osoittaa osoitteeseen on: 0x5449fff84c
      refA:n osoittaman muistipaikan arvo on: 5
      

  3. Lisää muuttuja int muuttuja b ja anna sen arvoksi 6.
  4. Kokeile voitko muuttaa refA:n osoittamaan b:n osoitteeseen?
  5. Kokeile voitko muuttaa pointerA:n osoittamaan b:n osoitteeseen?

Nyt sinun tulisi havaita mitä eroa on seuraavilla:

  • pointerA ja *pointerA
  • refA ja &refA
Ja lisäksi voit havaita, että pointterin voi myöhemmin asettaa osoittamaan eri muistipaikkaan, mutta referensille alustettua osoitetta ei voi vaihtaa.


Olio argumenttina

  1. Lisää sovellukseen luokka ClassB, ja siihen
    1. private string muuttuja nimeltään info
    2. get ja set metodit muuttujalle info
  2. Lisää sovellukseen luokka ClassA1, jonka h-tiedostossa koodi:
    class ClassA1
    {
    private:
        ClassB objectB;
    public:
        ClassA1(ClassB); //Luodaan kopio ClassB-luokan oliosta
        string getBinfo();
        void setBinfo(string);
    };
    
    Ja cpp-tiedostossa koodi:
    ClassA1::ClassA1(ClassB value):objectB(value)
    {
    }
    
    string ClassA1::getBinfo()
    {
        return objectB.getInfo();
    }
    
    void ClassA1::setBinfo(string value)
    {
        objectB.setInfo(value);
    }
    
  3. Lisää main.cpp tiedostoon koodi:
    ClassB objB;
    objB.setInfo("Olion B asettama info");
    
    ClassA1 objA1(objB);
    objA1.setBinfo("Olion objA1 asettama info");
    
    cout<<"objB: "<<objB.getInfo()<<endl;
    cout<<"objA1: "<<objA1.getBinfo()<<endl;
    
  4. Suorita sovellus ja tutki tuloksia
Edellisen vaiheen tarkoitus on havainnollistaa, että alkuperäisen B-olion (objB) data ei muutu, vaikka muokkaat A1-olion dataa.

Referenssi argumenttina

  1. Lisää edelliseen tehtävään luokka ClassA2, jonka h-tiedostossa koodi:
    class ClassA2
    {
    private:
        ClassB &refB;
    public:
        ClassA2(ClassB&); //Annetaan argumenttina B-luokan olion osoite
        string getBinfo();
        void setBinfo(string);
    };
    
    Ja cpp-tiedotosssa koodi:
    ClassA2::ClassA2(ClassB &value):refB(value)
    {
    }
    
    string ClassA2::getBinfo()
    {
        return refB.getInfo();
    }
    
    void ClassA2::setBinfo(string value)
    {
        refB.setInfo(value);
    }
    
  2. Lisää main.cpp tiedostoon rivit:
    ClassB &refB=objB;
    ClassA2 objA2(refB);
    objA2.setBinfo("Olion Agr asettama info");
    cout<<"objB: "<<objB.getInfo()<<endl;
    cout<<"objA2 "<<objA2.getBinfo()<<endl;
    cout<<endl;
    
  3. Suorita sovellus ja tutki tuloksia.

Edellisen vaiheen tarkoitus on havainnollistaa, että myös alkuperäisen B-olion(objB) data muuttuu, kun muokkaat A2-olion dataa.

Tehtävässä voidaan siis havaita, että kun oliolle A annetaan argumenttina olio B, niin A ei voi vaikuttaa olion B dataan.
Jos oliolle A annetaan argumenttina olion B osoite, niin A:n muokkaus muuttaa B:n dataa.



Toggle Menu