Fizikus C++ labor

1. hét: make és C ismétlés2. hét: pontosság és pontatlanság3. hét: azonos nevű függvények, referencia
4. hét: egyszerű osztályok5. hét: konstruktor és operator overloading6. hét: osztály dinamikus adattaggal
9. hét: >> és << használata I/O-ra, statikus tagok10. hét / 1: STL vector10. hét / 2: STL string, algorithm
11. hét: generikus algoritmusok és osztályok12. hét: öröklés13. hét: heterogén kollekció
14. hét: C++11 kitekintő15. hét: Nagyházi bemutatás

13. hét: virtuális függvény, heterogén kollekció

Perzisztens objektumok

A perzisztencia azt jelenti, hogy egy objektum el tudja menteni és vissza is tudja tölteni magát. Ezt gyakran a << és >> operátorokkal oldjuk meg. Ezeknek az operátoroknak a használatát már ismerjük, ebben nincs újdonság. A << és >> operátorokat fájlba írásra és olvasásra is használhatjuk, ha nem a cin-t és cout-ot használjuk, hanem fájlsztrímeket (filestream).

 

Amire figyelnünk kell, hogy a kiírt adatot a beolvasó operátor be tudja olvasni.

 

A következő példa két esetet mutat be: egy egyszerűt, amikor csak számokat írunk a fájlba, és egy olyat, ahol szöveget is. A helyzet pont ugyanaz, mint ami C-ben is gondot tudott okozni: ha egy számot olvasunk be egy sorból, akkor a sor végi újsor karakter ottmarad. Ha legközelebb is számot olvasunk be, akkor ez nem jelent gondot, mert a beolvasás egyszerűen átugorja a whitespace karaktereket. Ha viszont szöveget és számokat vegyesen írunk ki, akkor a teljes sort beolvasó getline a sor végén otthagyott újsor karaktert fogja a következő sornak tekinteni. Ezt a példában úgy oldjuk meg, hogy mindent szövegként olvasunk be. A számokat tartalmazó sorból aztán sztringsztrímet csinálunk, és abból olvassuk ki a számokat.

 

Ebben a megoldásban tehát a számokat szóközzel, a szövegeket pedig újsorral választottuk el egymástól. Természetesen sok más megoldás is lehetséges, pl. vesszővel vagy pontosvesszővel elválasztás, de ennek kezelése bonyolultabb megoldást igényel.

#include <iostream>
#include <fstream>
#include <sstream>

class csakszam {
    int x;
    double y;
public:
    csakszam() :x{ 3 }, y{ 9.8 }{}
    void clear() { x = 0; y = 0; }
    friend std::ostream& operator<<(std::ostream& os, const csakszam& x) {
        os << x.x << ' ' << x.y << std::endl;
        return os;
    }
    friend std::istream& operator>>(std::istream& is, csakszam& x) {
        is >> x.x >> x.y; // hibakezeléssel: if(!(is >> x.x >> x.y)) throw ......;
        return is;
    }
};


class sztringis {
    int x;
    double y;
    std::string s;
public:
    sztringis() :x{ 3 }, y{ 9.8 }, s{ "Egy boszorka van." } {}
    void clear() { x = 0; y = 0; s = ""; }
    friend std::ostream& operator<<(std::ostream& os, const sztringis& x) {
        os << x.x << ' ' << x.y << std::endl;
        os << x.s << std::endl;
        return os;
    }
    friend std::istream& operator>>(std::istream& is, sztringis& x) {
        std::string sor;
        if (!std::getline(is, sor))
            throw std::runtime_error(">> sztringis: sikertelen olvasás (x y sora)");
        std::istringstream strs(sor);
        if(!(strs >> x.x >> x.y))
            throw std::runtime_error(">> sztringis: nem int és double van a sorban");
        if (!std::getline(is, x.s))
            throw std::runtime_error(">> sztringis: sikertelen olvasás (s)");
        return is;
    }
};


int main() {
    try {
        std::ofstream ofs{ "csakszam.txt" };
        csakszam cs;
        if (ofs.is_open()) {
            ofs << cs << cs << cs;
            ofs.close();
        }
        cs.clear();
        std::ifstream ifs{ "csakszam.txt" };
        if (ifs.is_open()) {
            ifs >> cs >> cs >> cs;
            ifs.close();
        }

        ofs.open("sztringis.txt");
        sztringis sis;
        if (ofs.is_open()) {
            ofs << sis << sis << sis;
            ofs.close();
        }
        sis.clear();
        ifs.open("sztringis.txt");
        if (ifs.is_open()) {
            ifs >> sis >> sis >> sis;
            ifs.close();
        }

        std::cout << cs << sis;
    }
    catch (const std::runtime_error& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Tájékoztató

Szeretnél demonstrátor lenni programozásból? Itt olvashatsz róla.

1. feladat

Egészítd ki az előző heti feladatban szereplő Ember-Focista osztályokat úgy, hogy alkalmasak legyenek heterogén kollencióban való tárolásra! A heterogén kollekció akkor is helyesen működjön, ha valamelyik leszármazott dinamikus adattagot tartalmaz! A main függvényben hozz létre heterogén kollekciót egy tömbben, melybe dinamikusan foglalva adod hozzá az objektumokat! Hívd meg az objektumok print függvényét, majd szabadttsd fel a dinamikusan foglalt elemeket!

2. feladat

Készítsd el a 11.-12. kisházit!

3. feladat

Készíts osztályhierarchiát részecskék tárolására, amely alkalmas heterogén gyűjteményben való tárolásra! A részecskék közös tulajdonsága, hogy mindegyik tudja a saját nevét és ki tudja írni a saját adatait, valamint vissza tudja adni a tömegét. Tömege csak konkrét részecskének van, általában egy részecskének nincs, ezért az ősosztály legyen absztrakt!

 

Valósítsd meg a Fermion, Bozon, Lepton és Kvark osztályokat megfelelő hierarchiában! Ezek tényleges vagy absztrakt osztályok? Valósítsd meg az Elektron,Foton, Up(kvark), Down(kvark), Gluon osztályokat! Ezek tényleges vagy absztrakt osztályok? (Az egyszerűség kedvéért egyfajta gluont tételezzünk fel.)

 

Tedd lehetővé összetett részecskék létrehozását: hozz létre hadron és proton osztályt! Tipp: a proton egyfajta részecske, de nem egyfajta kvark vagy egyfajta gluon, ezért ezekből nem is származhat. A proton tartalmaz három kvarkot (két up és egy down), valamint három gluont.

 

A main függvényben hozz létre heterogén kollekciót a részecskékből, és mutasd be a használatukat!

Mintamegoldások

1.feladat (a változások kiemelve)
#include <iostream>
#include <string>

class Ember{
    std::string nev;
    int kor;
    bool lany_e; // tfh ha nem lány, akkor fiú
public:
    Ember(const std::string &nev, int kor, bool lany_e) :nev(nev), kor(kor), lany_e(lany_e){}
    virtual ~Ember(){}
    const std::string &getNev()const{ return nev; }
    int getKor()const{ return kor; }
    bool getLany_e()const{ return lany_e; }
    bool fetFiu_e()const{ return !lany_e; }
    void setNev(const std::string &ujnev){ nev = ujnev; }
    void setKor(int ujkor){ kor = ujkor; }
    void setLany_e(bool lany_e){ this->lany_e = lany_e; }
    void setFiu_e(bool fiu_e){ lany_e = !fiu_e; }
    virtual void print()const{
        std::cout << "Nev: " << nev << "\nKor: " << kor
            << "\nNeme: " << (lany_e ? "Lany" : "Fiu") << std::endl;
    }
};

class Focista :public Ember{
    int golok, valogatott;
public:
    Focista(const std::string &nev, int kor, bool lany_e, int gol, int valogatott)
        :Ember(nev, kor, lany_e), golok(gol), valogatott(valogatott){}
    int getGol()const{ return golok; }
    int getValogatott()const{ return valogatott; }
    void setGol(int gol){ golok = gol; }
    void setValogatott(int valogatott){ this->valogatott = valogatott; }
    void print()const{
        Ember::print();
        std::cout << "Gol: " << golok << "\nValogatott: " << valogatott << std::endl;
    }
};

int main(){
    Ember *tomb[3];
    
    tomb[0] = new Ember("Feles Elek", 115, false);
    tomb[1] = new Focista("Rugolabu Juliska", 19, true, 847, 12);
    tomb[2] = new Focista("Boci Joci", 39, false, 6, 0);

    for (int i = 0; i < 3; i++)
        tomb[i]->print();

    for (int i = 0; i < 3; i++)
        delete tomb[i];

    return 0;
}