Uceni na zkousku z objektove orientovaneho programovani, jak uz vetsina studentu objevila, by melo obsahova dve casti: strucne se zorientovat v problematice programovani v c++ a vyzkouset si test z predchozich let. Ukazky z testu jsou na forech, ovsem nektera zadani jsou tam nepresne a vyjimecne se vyskytne i chybna odpoved. Zkusila jsem tedy pomoci materialu z tohoto fora a z me zkousky sestavit tento dokument.
Presto, ze jsem se snazila, aby odpovedi zde byly spravne, mohla se mi vloudit chyba. Kdybyste nejakou objevili, dejte mi prosim vedet :)
a jestli zkousku neudelate, nesvalujte vinu na me :)
Toto je vytah otazek z testu z predchozich let - cerpala jsem ze sve zkousky, z prispevku na foru http://mff.fear.cz/forum/viewforum.php?f=25 a ze slidu z prednasek. Dekuji prednasejicim i spoluzakum, kteri se sverili s obsahem svych testu :)
Me velike diky patri taky tem, co mi pisi k tomuto webu komentare, poznamky, opravuji chyby a doplnuji informace.
Pro zvladnuti skutecneho testu by melo postacit pochopit tyto vzorove otazky :)
Za pomoc s pripravou na mou zkousku dekuji vsem, co do fora prispeli svymi testy a co mi poradili, kdyz jsem neco nechapala.
Test je delany zaskrtavaci formou, spravne muze byt jedna a vice odpovedi. Ovsem pozor - trestne body se pocitaji jako rozdil tvych a spravnych odpovedi. Tedy napriklad spravne je moznost A a ty zaskrtnes B, pak mas hned dva body dolu (prvni chyba je nezaskrtnute A a druha chyba je zaskrtnute B). Proto se obcas vyplati strategie - kdyz si nejsem jista, nezaskrtnu nic :)
Testy nejsou studentum vraceny zpet, takze nektere varianty odpovedi se nezachovaly - zverejny jsou jen ty spravne, ktere si nekdo zapamatoval :)
Znamkovani bylo takove:
0 - 2 chyby: 1
3 - 5 chyb: 2
6 - 8 chyb: 3
A jeste jedna dobra rada: poradne si precteti zadani! Pisemka je plna mist, kde lze lehce neco duleziteho prehledout a na pozdejsi reklamace nebude bran zretel :)
co je to singleton?
odpoved:
trida, ktera ma pouze jednu instanci
Predpokladejme tyto deklarace:
class T
{
public:
virtual void f();
}
class U: public T
{
public:
virtual void f();
}
U x;
T y=x;
y.f()
odpoved:
T::f()
Predpokladejme tyto deklarace:
class Base
{
public:
virtual Base operator+ (const Base &) const;
}
class Complex;
class Real:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Real operator+ (const Real &) const;
virtual Complex operator+ (const Complex &) const;
}
class Complex:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Real operator+ (const Real &) const;
virtual Complex operator+ (const Complex &) const;
}
Real r;
Complex c;
Base &b = r;
b = b + c;
[A] Real::operator+ (const Base &) const
[B] Complex::operator+ (const Complex &) const
[C] Complex::operator+ (const Base &) const
[D] Complex::operator+ (const Real &) const
odpoved:
A
(protoze pred b je v deklaraci &, je odkaz na cast objektu typu real, proto se pouzije funkce definovana ve tride real.)
Kdy se vola konstruktor prvku dynamicky alokovaneho pole?
[A] tesne pred prvnim pristupem k prvku
[B] na prvky pole sa nevolaji konstruktory
[C] prvky pole nesmi mit konstruktory
[D] automaticky po naalokovani pole
odpoved:
D
namespace T
{
double f(char x);
};
namespace U
{
char f(double d);
};
int f(int i);
using namespace T;
using namespace U;
char x = f('A');
[A] T::f(char)
[B] U::f(int)
[C] nelegalni volani
[D] U::f(double)
odpoved:
A
(pri pretezovani funkci se vybere ta funkce, pro kterou je konverze nejlevnejsi. tady je odpoved zrejma - pro char ani nemusime konverzi delat.)
class T
{
public:
T();
T(const T &);
T(int);
}
void f(const T & p) {}
[A] T::T()odpoved:
[B] T::T(const T &)
[C] zadnym
[D] T::T(int)
C
(predavame odkaz - zadny objekt nevznika ani se nekopiruje)
otazka:
Ktera metoda neni vhodna pro tridu T?
[A] T & operator= (T &) constodpoved:
[B] T()
[C] T & operator= (const T &)
[D] T(const T &)
A
(operator = by nemel byt konstantni, aby mohl prirazovat hodnotu)
templatestruct T
{
enum { v = 1 };
}
templatestruct T
{
enum { v = 2 };
}
templatestruct T
{
enum { v = 3 };
}
char a[ T::v];
[A] neni definovane
[B] 2
[C] 3
[D] 1
odpoved:
C
(jestlize alespon jeden typ je presne urcen, ma tato definice prednost)
class SStk
{
public:
/* ... */
void push(const std::string & s);
private:
std::string * p_;
int allocated_, used_;
};
void SStk::push (const std::string & s)
{
[1] if (used_ >= allocated)
[2] {
[3] int n2 = (allocated_ +1) * 2;
[4] std::string * p2 = new string[n2];
[5] for(int i = 0; i < used_; ++i)
[6] p2[i] = p_[i];
[7] delete[] p_;
[8] p_ = p2;
[9] allocated_ = n2;
[a] }
[b] p_[used_] = s;
[c] ++used_;
}
odpoved:
4, 6, b
(4 - pro nedostatek pameti. 6 - to, ze jsme zvetsili alokovanou pamet dvakrat jeste neznamena, ze je vetsi nez used; navic opet muze spadnout pro nedostatek pameti (volani copy konstruktoru operatorem =, tedy alokace pameti). b - vubec nezkoumame velikost s; opet alokujeme pamet v copy konstruktoru)
otazka:
Pokud nastane vyjimka:
[A] zanecha zasobnik v nezmenenem stavu
[B] muze zpusobit ztratu (nedostupnost) alokovane pameti
[C] muze zanechat zasobnik v nekonzistentnim stavu, ktery muze zpusobit behovou chybu
odpoved:
B
(B - Nekonzistentni stav je takovy stav, ve kterem je cast prvku v zasobniku v poradku (tedy platne ukazatele) a cast ukazatelu ukazuje na nejake nahodne misto v pameti. A ted proc se zasobnik nemuze dostat do nekonzistentniho stavu? Cely trik je skryty v radku [8]. Kdyz vznikne vyjimka na radku [6], nachazi se pole p2 v nekonzistentnim stavu ... avsak radek [8] se uz nevykona. To znamena, ze v zasobniku zustanou stare prvky p_ , ktere jsou konzistentni. -> zaslal Peto Cerno)
Kdy se vyhodnoti konstruktor globalni promenne?
odpoved:
pred vstupem do main
v jakem poradi se volaji konstruktory tridy? (datove polozky, predci tridy, trida)
odpoved:
predci tridy, datove polozky, trida samotna
v jakem poradi se volaji destruktory tridy? (datove polozky, predci tridy, trida)
odpoved:
trida samotna, datove polozky, predci tridy
(v opacnem, nez kostruktory)
ktera z techto funkci se nejvic hodi pro implementaci scitani dvou komplexnich cisel:
[A] Complex operator+(Complex a, Complex b);
[B] Complex& operator+(const Complex& a,const Complex& b);
[C] Complex operator+(Complex& a, Complex& b)const;
[D] Complex operator+(const Complex& a, const Complex& b);
odpoved:
D
(vhodne je vracet hodnotou, globalni funkce by nemela byt const, argumenty by mely byt const, aby funkce mohla zpracovavat i konstantni argumenty)
class T
{
public:
double f(char c)
{
printf("double char");
return c;
}
};
class U:public T
{
int f(int i)
{
printf("int int");
return i;
}
public:
char f(double d)
{
printf("char double");
return (int)d;
}
};
void main (void)
{
U z;
char x = z.f('A');
}
odpoved:
tento kod skonci s chybou "cannot acces private member declared in class 'U'"
(pri pretezovani funkci se neberou v uvahu funkce zdedene, nejlevnejsi konverze z char je na int, ale ta je privatni)
Jaky musi mit destruktor abstraktni trida?
[A] virtualni
[B] ciste virtualni
[C] zadny
odpoved:
A
Jaky je rozdil?
class T1
{
public:
int a;
void f();
}
struct T2
{
int a;
void f();
}
[A] T1 nelze prirazovat
[B] T2 nelze prirazovat
[C] zadny
odpoved:
C
(struct je synonymum pro class-public)
class base
{
public:
virtual base operator+(base &);
}
class real: public base
{
public:
virtual base operator+(base &);
real operator+(real &);
}
class complex: public base
{
public:
virtual base operator+(base &);
complex operator+(complex &);
}
real r;
complex c;
base b=r;
b=b+c;
[A] complex complex::operator+(complex &);
[B] real real::operator+(real &);
[C] base complex::operator+(base &);
[D] base base::operator+(base &);
odpoved:
D
(b je typu base, protoze to neni odkaz, ani ukazatel)
class Complex
{
public:
double Re, Im;
Complex(Re=0.0, Im=0.0);
Complex operator+(Complex &);
}
Complex Complex::operator+(Complex & b)
{
double r = Re + b.Re;
double i = Im + b.Im;
???;
}
[A] return Complex(r) + Complex(i);
[B] return * this;
[C] return Complex(r, i);
[D] neni legalni
odpoved:
C
class Complex
{
public:
double Re, Im;
Complex(Re=0.0, Im=0.0);
Complex operator+(Complex &) const;
}
Complex Complex::operator+(Complex & b) const
{
Re = Re + b.Re;
Im = Im + b.Im;
???;
}
[A] return Complex(r) + Complex(i);
[B] return * this;
[C] return Complex(r, i);
[D] neni legalni
odpoved:
D
(funkce je konstantni, nemuze menit data v objektu)
class T
{
T();
T(int);
T(const T &);
}
[A] T::T();
[B] T::T(int);
[C] T::(const T&);
odpoved:
C
(pri predavani hodnoty do funkce se objekt kopiruje, proto copy-konstruktor)
f(std::vectorv)
{
[A] std::vector::iterator it;
[B] it=std::find(v.begin(), v.end(), 0);
[C] v.insert(it, -1);
[D] v.insert(it+1, 1);
}
odpoved:
D
(po insertu se vsechny iteratory zneplatni)
class A
{
public:
virtual f();
}
class B: public A
{
public:
virtual f();
}
B b;
A a=b;
a.f();
[A] A::f()
[B] B::f()
odpoved:
A
(virtualni funkce se v potomcich redefinuje. zavola se ta, ktera patri k 'volajicimu' objektu.)
na kterych radcich muze nastat vyjimka?
f(std::vectorv)
{
[A] std::vector::iterator it;
[B] it=std::find(v.begin(), v.end(), 0);
[C] v.insert(it+1, 1);
[D] v.insert(it, -1);
}
odpoved:
C, D
(C - pokud bychom nulovy prvek nenasli, D - pokud by C proslo, po insertu jsou iteratory neplatne)
kdy se vykonaji konstruktory nestatickych polozek objektu?
[A] pri dynamicke alokaci
[B] po skonceni konstruktoru
[C] az je potreba
[D] pred telem konstruktoru objektu
odpoved:
D
(pozor - nestaticke polozky neznamenaji dynamicke, ale polozky, ktere nejsou uvozene slovem static)
jaky by mel byt konstruktor abstraktni tridy?
[A] private
[B] public
[C] protected
[D] zadny
odpoved:
C
Class U
{
U() {a = 1}
U(int i) {a= i + 2}
int a;
}
Class T: public U
{
T() : U(2) {}
T(int i) {a = a + 3}
T(const U &p) : U(p.a) {}
}
T x = U();
[A] 4
[B] 3
[C] 5
[D] 1
odpoved:
B
(nejdriv se zavola U(), takze a=1. potom konverzni konstruktor z T na U)
co je konzistentni stav?
odpoved:
- nedostupna data byla korektne destruovana a odalokovana
- ukazatele nemiri na odalokovana data
- plati dalsi invarianty dane logikou aplikace
jaky je nejvhodnejsi operator+= pro Complex
[A] Complex operator+=(const & Complex)
[B] Complex& operator+=(const & Complex)
[C] Complex& operator+=(const & Complex, const & Complex)
[D] Complex& operator+=(const & Complex, const & Complex) const
odpoved:
B
trida SStk implementuje zasobnik retezcu takto:
class SStk
{
public:
/* ... */
void pop(std::string & out);
private:
std::string * p_;
int allocated_, used_;
}
void SStk::pop(std::string & out)
{
[a] if(used_)
{
[b] --used_;
[c] out=p_[used_];
}
}
[A] zanecha zasobnik v nezmenenem stavu
[B] zanecha zasobnik ve zmenenem, avsak konzistennim stavu
[C] zanecha zasobnik v nekonzistentnim stavu
odpoved:
c, B
(c - muze dojit pamet, B - used_ se jiz odecetlo, coz je spravne. pri vyjimce se nic nevrati, ale stav zasobniku bude zmeneny a v podstate stejny, jako by k vyjimce nedoslo)
predpokladejme tyto deklarace:
class T
{
public:
int a;
};
class U : public T
{
public:
int b;
};
T x;
U y;
x=y;
[A] dojde k preteceni dynamicky alokovane pameti
[B] cast objektu y se okopiruje na misto objektu x
[C] prikaz bude kompilatorem oznacen jako chybny
[D] objekt x zanikne a misto nej vznikne kopie y
odpoved:
B
ktery z techto globalnich operatoru je nejvhodnejsi jako implementace scitani komplexnich cisel?
[A] Complex operator+ (Complex &, Complex &)
[B] Complex operator+ (const Complex &, const Complex &)
[C] Complex operator+ (const Complex &, const Complex &) const
[D] const Complex operator+ (const Complex &, const Complex &)
odpoved:
B
(A - kdyby byly argumenty const, tak je nevezme. C,D - ty const z toho delaji nepouzitelne funkce - nebo hodne tezko pouzitelne)
trida SStk implementuje zasobnik retezcu takto:
class SStk
{
public:
/* ... */
void pop(std::string & out);
private:
std::string * p_;
int allocated_, used_;
}
void SStk::pop(std::string & out)
{
[a] if(used_)
{
[b] out=p_[used_-1];
[c] --used_;
}
}
[A] zanecha zasobnik v nezmenenem stavu
[B] zanecha zasobnik ve zmenenem, avsak konzistennim stavu
[C] zanecha zasobnik v nekonzistentnim stavu
odpoved:
b, A
(b - muze dojit pamet)
Predpokladejme tyto deklarace:
class Base
{
public:
virtual Base operator+ (const Base &) const;
}
class Complex;
class Real:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Real operator+ (const Real &) const;
virtual Complex operator+ (const Complex &) const;
}
class Complex:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Complex operator+ (const Complex &) const;
virtual Complex operator+ (const Real &) const;
}
Real r;
Complex c;
Base b = r;
b = b + c;
[A] Real::operator+ (const Real &) const
[B] Real::operator+ (const Base &) const
[C] Complex::operator+ (const Real &) const
[D] Base::operator+ (const Base &) const
odpoved:
D
(b je typu base)
predpokladejme tyto deklarace:
class T
{
public:
int a;
};
class U : public T
{
public:
int b;
};
U x;
T y;
x=y;
[A] prikaz bude kompilatorem oznacen jako chybny
[B] objekt x zanikne a misto nej vznikne kopie y
[C] promenna x se presmeruje na objekt y
[D] okopiruje cely objekt y na misto objektu x
odpoved:
A
(nemuzeme 'mensi' (rodice) objekt nakopirovat do 'vetsiho' (potomka))
(kod je nesmyslny - to neni omyl. skutecne existuje varianta pisemky, ve ktere se vyskytuje)
trida SStk implementuje zasobnik retezcu takto:
class SStk
{
public:
/* ... */
void push(const std::string & s);
private:
std::string * p_;
int allocated_, used_;
};
void SStk::push (const std::string & s)
{
[1] if (used_ >= allocated)
[2] {
[3] int n2 = (allocated_ +1) * 2;
[4] std::string * p2 = new string[n2];
[5] for(int i = 0; i < used_; i++)
[6] p_[i] = p2[i];
[7] delete[] p2;
[8] p_ = p2;
[9] allocated_ = n2;
[a] }
[b] p_[used_] = s;
[c] ++used_;
}
[A] zanecha zasobnik v nezmenenem stavu
[B] muze zpusobit ztratu (nedostupnost) alokovane pameti
[C] muze zanechat zasobnik ve stavu neodpovidajicim uvedenemu konzistentnimu stavu
odpoved:
4, 6, b, B, C
(4 - pro nedostatek pameti. 6 - to, ze jsme zvetsili alokovanou pamet dvakrat jeste neznamena, ze je vetsi nez used; navic opet muze spadnout pro nedostatek pameti (volani copy konstruktoru operatorem =, tedy alokace pameti). b - vubec nezkoumame velikost s; opet alokujeme pamet v copy konstruktoru; B - ztratime nove alokovanou pamet; C - kvuli te ztrate pameti)
Predpokladejme tyto deklarace:
class Base
{
public:
virtual Base operator+ (const Base &) const;
}
class Complex;
class Real:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Real operator+ (const Real &) const;
virtual Complex operator+ (const Complex &) const;
}
class Complex:public Base
{
public:
virtual Base operator+ (const Base &) const;
virtual Complex operator+ (const Complex &) const;
virtual Complex operator+ (const Real &) const;
}
Real r;
Complex c;
Base & b = r;
b = b + c;
[A] Base::operator+ (const Base &) const
[B] Real::operator+ (const Base &) const
[C] Real::operator+ (const Complex &) const
[D] Complex::operator+ (const Real &) const
odpoved:
B
(jsou dve faze:
1) overloading
2) virtual methods
1) overloading je pri prekladu, zjistuje se ktera funkce ze vsech moznych se na zaklade parametru zavola. B je base, C je complex, B + C je operator+ becka s parametrem Complex. B je Base a Base ma jedinou moznost 'Base operator+ (const Base &) const'. kdyby v Base bylo treba 'Complex operator+ (const Complex &) const' tak by se volalo Complex a ne Base. proste se koukne a najde nejlevnejsi overloading. tady je jediny mozny.
2) za behu: za behu se pers * a & pouziva VMT, takze v b je Real r, takze se pouzije VMT a koukne se do Real::operator+ (const Base &) const)
8 komentářů:
díky s0cketko
(stejne otazky jsou pry ted na c++)
U otázky 4 by se možná mělo dodat, že typ návratové hodnoty funkce se neúčastní přetěžování.
Jinak díky, pomohlo ;-)
Hi
http://www.georgiawrestling.net/ - cheap levitra
Levitra - Revive your relationshipPurchase low cost Levitra (Vardenafil) at reputable online pharmacy and save big money.
[url=http://www.georgiawrestling.net/]levitra pills[/url]
Levitra - Revive your relationshipPurchase low cost Levitra (Vardenafil) at reputable online pharmacy and save big money.
generic levitra online
But just assure that you are taking this drug in the right amount and under the guidance of your doctor or physician.
Díky za vypracování - je to parádní zdroj.
Jenom u otázky č. 20 je sice vybraná správná možnost, ale se špatným zdůvodněním - ve skutečnosti tam dochází ke slicingu, protože se do předka uloží jenom část potomka.
Děkuji za právě udělanou zkoušku a myslím, že můžu mluvit i za zbytek lidí z (nejen) tohoto termínu :)
Robert
socketko, pozri san na siestu otazku... template struct neexistuje ;)
Doplnil bych tuto otázku:
----------------------------------------
class A { public:
virtual int f() { return 1; };
int g() { return 2; };
int h() { return f(); };
virtual int j() { return g(); };
};
class B : public A { public:
virtual int f() { return 3; };
int g() { return 4; };
int h() { return g(); };
virtual int j() { return f(); };
};
A x; B y;
A * p = &x;
A * q = &y;
B * r = &y;
xy.fghj();
pqr -> fghj();
----------------------------------------
V testu jsou čtyři náhodně vybrané kombinace (např. r->f(); q->h(); ...). Doporučuji si vše vyzkoušet, jen kvůli této otázce jsem měl dvojku.
Jinak díky za zbytek otázek, opravdu pomohly.
Okomentovat