1. Kérdések

slido.com #cppftw-prog2

Beugrókérdések

  • igaz
  • inkább igaz
  • inkább hamis
  • hamis

3. 1-5. kérdés

  1. Az iterátorokat váró függvényeivel tömbökön is lehet dolgozni.
  2. Referenciája csak lokális és globális változónak lehet.
  3. Egy osztály konstans adattagja a konstruktor törzsében kaphat értéket.
  4. Minden iterátor dereferálható.
  5. Template függvény hívásakor mindig meg kell adnunk a template paramétereket.
Megoldás
  1. I
  2. H, létezik heap is
  3. H, inicializáló listán
  4. I
  5. H, ez a template paraméterek levezetése

4. 6-10. kérdés

  1. Kivételt csak abban a függvényben kaphatjuk el, ahol eldobtuk.
  2. Többszörös öröklésnél mindig szükség van virtuális öröklésre.
  3. A new operátor értékét mindig ellenőrizni kell, mert ha elfogy a memória, NULL pointert kapunk.
  4. Konstruktorból és destruktorból nincs sok értelme virtuális függvényt hívni.
  5. Az inicializáló listán mindig az ott szereplő sorrendben történik az inicializálás.
Megoldás
  1. H
  2. H
  3. H
  4. (pontatlan megfogalmazás, de) I
  5. H, a deklaráció sorrendjében

5. 11-15. kérdés

  1. Az egyparaméteres konstruktor használható automatikus típuskonverzióra.
  2. Az unáris predikátumot hívják komparátornak.
  3. Az implicit operator= meghívja az adattagok értékadó operátorát.
  4. Tartalmazott objektum destruktora mindig lefut, ha a tartalmazó destruktora lefut.
  5. A ++iit és az iit++ kifejezés ugyanazt az operátort hívja.
Megoldás
  1. I
  2. H, a komparátor a bináris
  3. I
  4. I
  5. H

6. 16-20. kérdés

  1. Az alábbi kódrészlet biztosan hibás:

Almafa::Almafa(Almafa const & a1) { Almafa a2 = a1; }

  1. A nyíl operátor nem overload-olható.
  2. Az inicializáló lista a konstruktor törzse után fut le.
  3. Virtuális destruktorra akkor is szükség van, ha az adott osztálynak nincs virtuális függvénye.
  4. A leszármazott osztály destruktora minden esetben meghívja az ősosztály destruktorát.
Megoldás
  1. I, végtelen rekurzió
  2. H
  3. H, előtte
  4. H, de Prog2-n néha igaz
  5. I

7. 21-25. kérdés

  1. A new által allokált hely felszabadítható free-vel is.
  2. Absztrakt ősosztálynak kell, hogy legyen virtuális metódusa.
  3. Ha egy ősosztálynak van virtuális destruktora, minden leszármazottnak kell destruktort írjunk.
  4. A referencia csak paraméterátadásra használható.
  5. Az std::vector<int>::iterator iit = l.begin();

sor után iit + 1 hatására az iit iterátor ugrik a következő elemre.

Megoldás
  1. H, mindenképpen delete kell
  2. I, ráadásul tisztán virtuális
  3. H, megoldja a fordító
  4. H, van referencia változó is
  5. H, az a kifejezés új iterátort ad vissza

8. 26-30. kérdés

  1. A fordító által generált másoló konstruktor meghívja az adattagok másoló konstruktorát.
  2. A begin() és az end() az iterátorok jellemző tagfüggvényei.
  3. A leszármazottban felüldefiniált virtuális függvény minden esetben meghívja az ősosztály megfelelő virtuális függvényét.
  4. std::list<int>::const_iterator segítségével nem járható be a lista, mert az iterátor konstans, mindig ugyanarra az elemre mutat.
  5. A virtuális függvény mindig lassabb, mint a nem virtuális.
Megoldás
  1. I
  2. H, a tárolóé
  3. H, előtte
  4. H, de Prog2-n néha igaz
  5. I

9. 31-35. kérdés

  1. A delete null pointer esetén kivételt dob.
  2. std::vector<std::string> nem létezhet, mert az std::string-ek dinamikusak, és memóriaszivárgás keletkezne.
  3. Kivétel dobása előtt meg kell hívnunk a destruktorokat, különben memóriaszivárgás lesz a programban.
  4. Template osztály példányosításakor mindig meg kell adnunk a template paramétereket.
  5. Publikus öröklésnél a leszármazott osztály az ősosztály minden tagfüggvényét megörökli.
Megoldás
  1. H, szabvány szerint nem csinál semmit
  2. H
  3. H, automatikusan meghívódnak a destruktorok
  4. I, levezetés csak függvényeknél van
  5. I (kivéve a konstruktort)

10. 36-40. kérdés

  1. Az operator+= automatikusan keletkezik, ha van operator+.
  2. Az eleje-vége iterátorpár konvenció szerint balról nyitott, jobbról zárt intervallum.
  3. Bármelyik osztály példányosítható.
  4. Beugróban az STL vagy C++ puskából néhány igazhamis megoldása egy az egyben kiolvasható.
  5. Ha funktorokkal szeretnénk dolgozni, template kódot kell írnunk.
Megoldás
  1. H, ez két különböző operátor
  2. H, pont fordítva
  3. H, az absztrakt osztályok nem
  4. I, nyomtass!
  5. H, operator() nem csak template osztálynak lehet

11. 41-45. kérdés

  1. Az std::find visszatérési értéke egy iterátor.
  2. Két azonos típusú iterátor között definiált az egyenlőség operátor.
  3. Publikus öröklésnél a leszármazott osztály az ősosztály minden konstruktorát megörökli.
  4. Vannak olyan iterátorok, amin n léptetés megoldható egyetlen lépéssel, de nem mindegyiken.
  5. Az std::remove(it1, it2, érték) nem törli ki a tárolóból az elemeket.
Megoldás
  1. I, iterátor a megtalált elemre, vagy az end
  2. I
  3. H
  4. I, it += n, de lista iterátorának nincs
  5. I, csak az elejére rakja a többit

12. 1. nagyfeladat

Írj függvényt, amely tetszőleges, szabványos iterátorokkal rendelkező tárolót vesz át paraméterként, és kiírja a képernyőre a tárolóban tárolt elemeket! Az egyes elemek legyenek vesszővel elválasztva.

13. 1. nagyfeladat: mintamegoldás

template <typename T>           /* 2 */
void print(T const & tarolo) {  /* 1, 3 */
  bool elso = true;
  for (typename T::iterator iit = tarolo.begin(); /* 4, 5 */
       iit != tarolo.end();                       /* 5, 6 */
       ++iit)                                     /* 7 */
  {
       if (!elso)                                 /* 10 */
           std::cout << ", ";                     /* 9 */
       std::cout << *iit;                         /* 8 */
       elso = false;
  }
}
for (auto iit = tarolo.begin(); iit != tarolo.end(); ++iit)
     std::cout << *iit; // ez is jó

for (auto const & elem : tarolo)
     std::cout << elem; // ez is jó

14. 1. nagyfeladat: pontozás

  • 2p a tároló van átvéve paraméterként, semmiképp sem iterátorok!
  • 1p sablon függvény kell
  • 1p const& szerint van átvéve, nem másoljuk le a kiírás kedvéért
  • 1p T::iterator a típusa az iterátornak (kell a typename, de a pont jár anélkül is)
  • 1p a tároló .begin() és .end() függvényének hívása
  • 1p a tároló végének vizsgálata != operátorral (< nem biztos, hogy jó)
  • 1p az iterátor léptetése ++ operátorral (mindegy, hogy pre- vagy post, ugyanakkor += 1 és iit = iit+1 nem biztos, hogy jó)
  • 1p * operátor használata az iterátoron
  • 1p a vessző kiírásának logikája
  • ajándék 1p, ha az elején/végén nincs vessző

15. 2. nagyfeladat

Írj függvényt, amely kiválasztott adatokat másol egyik helyről a másikra (copy_if)! A bemenő tartomány iterátorokkal adott, a cél tartomány eleje szintén. Az elemek kiválasztását (melyik a másolandó elem, melyik nem) egy paraméterként átvett predikátummal kell megoldani – ha az igazat ad, az elem másolandó. Adjon vissza a függvény egy iterátort, amely azt mutatja, meddig írt a cél helyre adatokat!

Miért van szükség a visszatérési értékre? Mutass példát, amelyben egy 10 elemű, egész számok std::list-ből másolod a páros számokat egy tömbbe!

16. 2. nagyfeladat: mintamegoldás

template <typename INIT, typename OUTIT, typename PRED> /* 2, 3 */
OUTIT copy_if(INIT begin, INIT end, OUTIT to, PRED p) { /* 1, 8 */
    for (INIT iit = begin; iit != end; ++iit) {         /* 4 */
        if (p(*iit)) {                                  /* 5 */
            *to = *iit;                                 /* 6 */
            ++to;                                       /* 7 */
        }
    }
    return to;                                          /* 8 */
}

bool paros(int i) { return i % 2 == 0; }

std::list<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };   /* 9 */
int cel[10];                                            /* 10 */

// Innen tudja a hívó, hogy hány adatelem lett a cél helyen.
int *eddig = copy_if(v.begin(), v.end(), cel, paros);   /* 11, 12 */
for (int *p = cel; p != eddig; ++p)                     /* 13 */
    std::cout << *p << ", ";

17. 2. nagyfeladat: pontozás

  • 2p a függvény paramétere 3 darab iterátor (ettől, eddig, ide)
  • 1p template a függvény ÉS a két iterátor (ettől+eddig, ide) típusa különböző lehet (2 külön template paraméter kell, lásd a példát)
  • 1p predikátum is template paraméter
  • 1p a tartomány bejárása, fontos: balról zárt, jobbról nyílt; *begin beletartozik, *end nem. iit < end nem jó, iit += 1 sem. a begin és az end a paraméterek, függvényhívás itt nem lehet!
  • 1p az elem olvasása az iteratoron keresztül (*iit, kell a csillag)
  • 1p az elem cél helyre írása az output iteratoron keresztül (*to = ...)
  • 1p output iterator lép és csak akkor lép, ha volt másolt adat
  • 1p output iterator visszaadása, a visszatérés típusa helyes
  • 1p példában a lista létrehozása (feltöltés lényegtelen)
  • 1p példa cél tömbje, legalább 10 elemű (lehet hogy mind páros!)
  • 1p függvény hívása, listán begin() és end() használata, paros() itt nem hívódik meg
  • 1p visszatérési érték eltárolása, int* típusú a változó
  • 1p tömb bejárása pointerrel, vagy i = 0; i < eddig-cel; ++i

18. 3.A. nagyfeladat

Írj programrészt, amelyik a szabványos bemeneten a fájl végéig olvas be valós számokat, és ezeket beteszi egy std::list-be! Összegezd a tároló elemeit az std::accumulate függvénnyel! (Ennek 3. paramétere az akkumulátor kezdeti értéke.)

19. 3.A. nagyfeladat: mintamegoldás

double dore;
std::list<double> l;
while (std::cin >> dore)
    l.push_back(dore);      // vagy push_front, nem specifikált
double osszeg = std::accumulate(l.begin(), l.end(), 0);

20. 3.A. nagyfeladat: pontozás

  • 1p lista létrehozása

  • 1p beolvasás fájl végéig

    (minden eof, null, 0, -1 és hasonló dolog esetén az egész feladat nulla pont)

  • 1p listába fűzés

    (ha nincs eltalálva a függvény neve, most jó az, csak a szándék érezhető legyen :D)

  • 1p accumulate hívása, lista begin és end függvényeinek használata (ne maradjon le a ())

  • 1p akkumulátor kezdeti értéke 0

21. 3.B. nagyfeladat

Hozz létre egy sztringeket tartalmazó halmazt! Tegyél bele néhány szót, majd járd be, és listázd ki a tartalmát! Használd az STL elemeit, de C++11 eszközöket most ne – írd ki a pontos típusokat!

22. 3.B. nagyfeladat: mintamegoldás

std::set<std::string> szavak;
szavak.insert("alma");
szavak.insert("körte");
szavak.insert("barack");
for (std::set<std::string>::iterator iit = szavak.begin();
     iit != szavak.end();
     ++iit)
{
    std::cout << *iit << std::endl;
}

23. 3.B. nagyfeladat: pontozás

  • 1p halmaz típusa, template paraméter sztring
  • 1p elemek beszúrása
  • 1p bejáráshoz iterátor típusa: tároló<miket>::iterator, esetleg const_iterator
  • 1p begin() tagfüggvény hívása a tárolón, legyen kint a ()
  • 1p end() tagfüggvény hívása a tárolón, legyen kint a ()
  • 1p iterátorokon használt műveletek, !=, ++ és *

24. 4. nagyfeladat: mitírki

#include <iostream>
using namespace std;

class A {
  private:
    int k;
  public:
    A(const int i = 0)    :k(i) { cout << 'k'; }
    A(const A& a)         { k = a.k; cout << 'c'; }
    void operator=(A uj)  { k = uj.k; cout << 'e'; }
    A operator*(int i)    { cout << i*100; return *this; }
    ~A()                  { cout << 'd'; }
};
A& operator*(int i, A& a) { cout << i; return a; }

int main() {
    A a(1);       cout << '\n';
    A b = a;      cout << '\n';
    a = a * 2;    cout << '\n';
    a = 3 * a;    cout << '\n';
}

25. 4. nagyfeladat: megoldás

#include <iostream>
using namespace std;

class A {
  private:
    int k;
  public:
    A(const int i = 0)    :k(i) { cout << 'k'; }
    A(const A& a)         { k = a.k; cout << 'c'; }
    void operator=(A uj)  { k = uj.k; cout << 'e'; }
    A operator*(int i)    { cout << i*100; return *this; }
    ~A()                  { cout << 'd'; }
};
A& operator*(int i, A& a) { cout << i; return a; }
int main() {
    A a(1);       cout << '\n'; // k
    A b = a;      cout << '\n'; // c
    a = a * 2;    cout << '\n'; // 200ced
    a = 3 * a;    cout << '\n'; // 3ced
    // dd
}

26. 5.A. nagyfeladat

Definiáld az AB osztályt, és az azzal közvetlen kapcsolatban lévő osztályokat! A tagváltozók értékeit a konstruktorparaméterek adják; a konstruktorokat írd is meg.

feladat_5

27. 5.A. nagyfeladat: mintamegoldás

class A {
  public:
    virtual void f() = 0;
    virtual ~A();
};

class B {
    int szam;
  public:
    B(int i) : szam(i) {}
    int getSzam() const;
    virtual ~B();
};

class AB : public A, public B {
    string nev;
  public:
    AB(int i, string s) : B(i), nev(s) {}
    void f();
};

28. 5.A. nagyfeladat: pontozás

  • 1p A osztály, publikusak a függvények
  • 1p A osztály, virtuális mindkettő, f() tisztán virtuális
  • 1p B osztály, privát adattag és publikus függvények
  • 1p B osztály konstruktorában szam = i
  • 1p AB osztály, öröklések (pontos szintaxis!)
  • 1p AB konstruktor hívja az ős konstruktorát

29. 5.B. nagyfeladat

A rajz összes osztálya rendelkezésére áll. Az std::vector sablon felhasználásával hozz létre egy olyan objektumot (tar), ami "tárolni" tud AA és AB típusú objektumpéldányokat is. Ezután a dinamikus memóriában hozz létre 100 db AB példányt és egy AA példányt úgy, hogy később elérd azokat! Ügyelj a konstruktorok paraméterezésére!

feladat_5

30. 5.B. nagyfeladat: megoldókulcs

std::vector<A*> tar;
for (int i = 0; i < 100; ++i)
    tar.push_back(new AB(1, "C++"));
tar.push_back(new AA(3.14));
  • 1p vektor használata
  • 1p példányosítás az ős pointerével (A*)
  • 1p AB-k létrehozása dinamikusan, new muszáj
  • 1p AA létrehozása dinamikusan, new itt is kell
  • 1p tárolóba be