std::hex, std::setw, std::fill
Az előadás objektum bájtjait kiíró programjában...
Hogy lehet printf()-fel megoldani a ciklusban lévő körülményes
kiírást?
Megoldás
printf("%02x ", ptr[i]);
A referencia mérete
Az előadás objektum bájtjait kiíró programjában...
Nem rossz ez a program? A sizeof(obj) nem a referencia méretét
adja? Hiszen az obj paraméter típusa konstans referencia. C-ben nem
volt szabad ilyet csinálni: ha indirekt módon, pointerrel adtunk át egy paramétert
(pl. tömböt), akkor a sizeof mindig a pointer méretét adta.
Itt mi a helyzet?
Megoldás
Nincs olyan, hogy „referencia mérete”. Egy objektum referenciája, azaz neve,
mindenben megegyezik az eredeti objektummal, tökéletesen megkülönböztethetetlen
attól. Ezért sizeof(obj)==sizeof(T) a függvényben. A referencia nem
objektum, és így nincs definiált mérete sem.
Érték kiírása
Az előadás objektum bájtjait kiíró programjában...
Működik az, ha nincs változó, csak egy értéket szeretnék kiírni a fenti függvénnyel?
Pl. helyes a print_obj_hex(1234); sor? Miért?
Megoldás
Igen, működik. A konstans referencia típusú paraméterek át tudnak venni jobbértékeket is, tehát olyan értékeket, amelyek nem változóban vannak tárolva, nincs nevük. Ilyenkor a fordító a hívás idejére létrehoz egy ideiglenes változót, és beteszi az értéket, hogy a függvény referenciaként megkaphassa azt.
Struct és class
Mi a különbség a class és a struct között?
Megoldás
Csak annyi, hogy a class-nál az adattagok (és az öröklések) alapértelmezetten
privátak, a struct-nál publikusak. Ezért a struct Rectangle : Shape egy
publikus leszármazást jelent.
Öröklés és tartalmazás
Ha az öröklésnél / tartalmazásnál is az objektum elejére kerül az ős objektum / tartalmazott objektum, akkor tulajdonképp mi a különség az öröklés és a tartalmazás között?
Megoldás
A memóriaképben ugyan semmi, de ez nem jelenti azt, hogy az öröklés és a tartalmazás között jelentésbeli különbség nincsen. Az öröklés „X egyfata Y”, a tartalmazás „X-nek van egy Y-ja” kapcsolatot fejez ki, és ez a programkód jelentése szempontjából sokat számít. Ettől függ az, hogy milyen konverziókat, paraméterátadásokat enged meg a fordító. Például nem származtathatunk egy pont típusból (x, y koordináták) téglalap típust azzal a céllal, hogy a téglalapnak legyen x és y koordinátája, mert akkor minden pontot váró függvénynek téglalapot is adhatunk paraméterként. A pont és a téglalap között nem leszármazási, hanem tartalmazási kapcsolat van: a téglalap nem egy pont, hanem a téglalapnak van egy pontja, amely a helyzetét meghatározza.
Offsetof I.
Az előadás programjában, a Az „objektum pointere plusz ofszet” kifejezés által egy pointer kapunk az adott adattagra.
Mivel a pont neve esetén az adattag típusa case TYPE_STRING részben mit jelent
a char*, és mit a char** cast? Melyik miért ilyen?
Megoldás
char*, az így kapott pointer char**
típusú. A (char*) cast pedig a bájtonkénti címzés miatt kell.
Offsetof II.
Az előbb említett kódban, az adattagokat elérő, *(valami + valami.ofszet) alakú kifejezések elég sok zárójelet
tartalmaznak. Elhagyható-e valamelyik zárójelpár, és miért?
Megoldás
((char*) &p) – itt elhagyható a külső pár. A következő operátor
az összeadás, amely alacsonyabb precedenciájú, mint a (char*) cast.
A sok zárójel
Tényleg kell a zárójel az előadás kódjában a
Nem, csak nagyon nehéz olvasni nélküle. A point_class_members[i].mptr köré?
Megoldás
.* operátor alacsonyabb precedenciájú,
mint a [] és . operátorok, ezért a zárójel elhagyható lenne. Egy ilyen
kifejezésben viszont látszik, hogy a .* jobb oldali operandusa egy teljes kifejezés
lehet, szemben a sima . operátorral, amelynek a jobb oldali „operandusa” egy adattag
neve lehet, semmi más.
Keresztkérdések
Az alábbi elméleti kérdésekre szövegben válaszolj, esetleg pár soros kódrészlettel illusztrálva, ha úgy látod hasznosnak! (Megjegyzések: 1. Az is lehet, hogy értelmetlen valamelyik kérdés. 2. Saját véleményt, meglátást írj, ne guglizz :D)
- Ha egyetlen egy mondatban kell megfogalmaznod, hogy mi a közük C-ben a pointereknek a tömbökhöz, mi lesz az az egy mondat?
- Hány bájtos egy referencia?
- Létezik-e referenciák tömbje? Vajon miért?
Reflektivitás – a tevékenység virtuális függvényben
A kiindulási alap az extrákban megjelenő írás kódja.
A programot át lehetne írni úgy, hogy a kiírásokat végző dynamic_cast sorozat helyett
a PointMptrBase osztályba egy virtuális függvényt teszünk:
class PointMptrBase {
public:
virtual ~PointMptrBase() {}
virtual void save_to_stream(std::ostream & os, Point const& p) const = 0;
};
template <typename T>
class PointMptr : public PointMptrBase {
public:
PointMptr(T Point::* mptr) : mptr(mptr) {}
T Point::* mptr;
virtual void save_to_stream(std::ostream & os, Point const& p) const {
os << p.*mptr;
}
};
int main() {
/* ... */
for (int i = 0; point_class_members[i].name; ++i) {
std::cout << point_class_members[i].name << " = ";
point_class_members[i].mptrobj->save_to_stream(std::cout, p1);
std::cout << std::endl;
}
/* ... */
}
Mi a véleményed erről az átalakításról? Vannak előnyei, vannak hátrányai?
Megoldás
- Megszűnt a
dynamic_cast, automatikusan megíródnak a függvények a sablonból. - Ha más működés kell bizonyos típusú adattagnál, egy adott
template <typename T> class PointMptrosztály specializálható.
- A
PointMptrBaseosztályba bekerült egy olyan tevékenység, amihez annak az osztálynak nincs köze (az adattag kiírása). Ide kerülne az összes többi tevékenység is; pl. dialógusablak létrehozásakor a szövegbeviteli mező, csúszka stb. elemek létrehozása. Ezek nem igazán tartoznak ehhez az osztályhoz. Ez feladatspecifikus, nem tartozik egy reflektivitást biztosító keretrendszerhez.
Reflektivitás – dynamic_cast
A kiindulási alap az extrákban megjelenő írás kódja.
Mi a helyzet ezzel a dynamic_cast() sorozattal, meg lehetne kerülni?
Megoldás
Meg, mint mindig. Betehetjük az MptrType<T> típusokba a teendőket.
Esetleg használhatjuk a látogató mintát is,
hogy külön osztályba kerülhessenek.
Reflektivitás – Visitor
Ez is az az extrákban megjelenő írás kódjára vonatkozik.
Oldd meg látogató mintával (Visitor pattern) a reflektív objektumok bejárását, az egyes adattagokon elvégzendő tevékenységeket!
Megoldás
Nincs mintamegoldás, de ha csináltál egyet, küldd el :D