# Zkouška 13.2.2012

<{ForumPost(poster="mathemage", timestamp=2012-02-14 23:03:26)}>
(1)                                                                                                                                                                        

    int a;
    int f(int p, int q) {
      a = p + q;
      p = a * q;
      return a+p;
    }
     
    int g() {
      a = 3;
      return f(a, a);
    }
    

   
Co vrati fce g?  
   
- 24.  
   
(2) Přepokládejme následující kód:

    class T {/* */};
    T * x = new T[100];
    

   
Jaká je správné dealokace x?  
   
- 

    delete [] x; 

   
(3) Otázka na téma tříd PES - SAVEC -ZVIRE (potomci a předci jako v přírodě:)  
   
Asi 4 varianty, 3 z nich byly typu

    foo = & new bar

což obecně je obskurnost, páč "new" vrací adresu na nově alokovaný objekt a  
"&" vrátí "adresu této adresy" (muselo by se přiřadit do dvojitého pointeru  
atp.)  
   
4. varianta byla: 

    ZVIRE *x = new PES

, je úplně správně (ukazatel  
    a polymorfismus, tj. žádný slicing z kopírování objektů)  
   
(4) Otázka na virtuální metody třídy a třídy z ní dědící. Většina otázek byla  
typu:

    T x;
    T *p = &x;
    

Co udělá fce "p->fce()", stačilo se dívat vyloženě jen na tu třídu, protože  
ukazatel ukazoval na objekt svého typu, takže žádná záludnost v tom nebyla.  
   
Pak tam byla otázka:

    class T {
      virtual int f() {return 1;}
      virtual int g() {return 2;}
      int h() {return f();}
    }
     
    class U : public T {
      virtual int f() {return 3;}
      virtual int g() {return 4;}
      int h() {return g();}
    }
     
    U y;
    T *p = &y;
    

   
Co vrátí "p->h()"?  
   
-3.  
Už bylo na socketce, jen stručně: Při kompilaci se určí, který prototyp fce se  
zavolá (v závislosti na počtu a typu parametrů, vybere se ta s nejlevnější  
konverzí parametrů). Protože je to pointer na třídu T, je to verze "T::h()",  
ta bude vyžadovat návratovou hodnotu fce f();  
V druhé fázi za běhu se pointer "p" na svoji VMT, to je VMT patřící "U", proto  
se volá "U::f()".  
   
(5)

    class T {
      virtual int f();
    }
     
    class U : public T {      
      virtual int f();
    }
     
    U y;
    T x = y;
    

   
Jaka fce se zavola pri x.f()?  
   
- T::f(), nepřiřazujeme referenci ani pointerem, takže VMT se nezkopiruje, ale  
zůstavá ta stará z "class T".  
   
(6)

    class U {
    public:
      int a;
     
      U() {a = 1;}
      U(int i) {a = i + 2;}
      U(const U & b) {a = b.a}
    };
     
    class T : public U {
    public:
      T() {}
      T(int i) {a = i + 3;}
      T(const U & b) : U(b.a) {}
    };
     
    T x = U();
    

   
Jakou bude mít na konci "x.a" hodnotu?  
   
- 3. (Nejprve bezparemtricky konstruktor "U()"...a == 1, tento objekt se  
zkopiruje do x pres copy-constructor "T(const U & b)", ten zavola "U(int  
i)"...a == 3)  
   
(7)

    class T {
    /* ... */
    public:
      virtual ~T();
    private:
      T(const T & x);
      T & operator=(const T & x);
    };
    

   
K čemu se hodí dvě výše uvedené privátní metody:  
   
- ke korektnímu kopírování objektů...tady mělo být NE, ale já měl, ANO (pokud  
by "T" definovala nějaké metody, které by je využívaly, obešlo by to tu  
skutečnost, že jsou private). Nakonec mi řekl, že by mi i tohle asi uznal, i  
když jsem to nepotřeboval, protože jsem z celýho testu měl zakroužkovaný jen  
tohle (a na dvojku můžou být "až" 2 zakroužkovaný chyby)  
- k zabránění nežádoucímu (ano, skutečně "nežádoucímu", nikoliv  
"nežádoucího":) kopírování...ANO (díky tomu, že jsou private, tak ani  
potomci to nedokážou)  
- k ničemu - deklaraci nelze překompilovat...NE (vše je v cajku)  
- k naplnění předepsaného rozhraní (tj. využitelnost ve standardních  
knihovnách, do kontejnerů atp.)...NE (opět kvůli tomu private)  
   
(8) 

    class Complex {
    /* ... */
    public:
      double Re, Im;
      Complex(double r=0.0, double i=0.0) : Re(r), Im(i) {}
      Complex & operator+=(const Complex & b) {
        Re = Re + b.Re;
        Im = Im + b.Im;
        ?????????
      }
    };
    

   
Co má být (vhodně) doplněno místo "?????????"_?  
   
- Bylo několik možností, všechny vracely hodnotou nějaký nový objekt Complex s  
potřebnými hodnotami, ale jediný správně jest:

    return * this;
    

   
(aby šly dělat třeba věci typu 

    Complex a, b;
    /* ... */
    a += a += b;
    

   
9) Označte řádek, kde může dojít k běhové chybě (neberte v úvahu bad_alloc,  
tj. nedostatek paměti)

    void f(std::vector<int> v) {
    [a]  std::vector<int>::iterator it;
    [b]  it = find(v.begin(), v.end(), 0);
    [c]  it = v.insert(it, -1);
    [d]  it = v.insert(it + 2, -2);
    }
    

   
- Jedině \[d], protože "it + 2" může jít mimo rozsah (až za nový "v.end()");
<{/ForumPost}>

