2. hét: Objektumok memóriaképe

Czirkos Zoltán · 2026.10.29.

1. Az előadással kapcsolatosan...

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 case TYPE_STRING részben mit jelent a char*, és mit a char** cast? Melyik miért ilyen?

Megoldás

Az „objektum pointere plusz ofszet” kifejezés által egy pointer kapunk az adott adattagra. Mivel a pont neve esetén az adattag típusa 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 point_class_members[i].mptr köré?

Megoldás

Nem, csak nagyon nehéz olvasni nélküle. A .* 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)

  1. 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?
  2. Hány bájtos egy referencia?
  3. Létezik-e referenciák tömbje? Vajon miért?

2. Reflektivitás

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 PointMptr osztály specializálható.
  • A PointMptrBase osztá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