(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?
(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.)
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?
(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;
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()");