Commit c23cec52 by Szeberényi Imre

v0

parents
/**
* \file activebg.h
* \brief ActiveBg osztály deklarációja
*
*/
#ifndef ACTIVEBG_H
#define ACTIVEBG_H
#include "widget.h"
/// Egy olyan grafikusan nem megjelenő widget, amire a callback
/// függvény tehető. A teljes képernyőn aktív.
/// A gomb "megnyomására" meghívódik a paraméterként kapott
/// osztály függvényhívás operátora a beállított int paraméterrel.
/// Azért template, hogy könnyebben alkalmazkodjon a különféle
/// callback függvényekhez, funktorokhoz.
template<class T = void (&)(const SDL_Event&, int) >
class ActiveBg : public Widget {
T& cb; ///< callback objektum referencia
int val; ///< int érték, amit átad a callback függvénynek
public:
/// Konstruktor elteszi a callback rutin címét és a híváskor
/// átadandó int paramétert
ActiveBg(T& cb, int val = 0) : cb(cb), val(val) { }
/// Mivel igazi ablak nincs, a teljes képernyő a tárolóhoz tartozik.
/// Minden pontot magáénak tekint.
bool contains(const Point& p) {
return true;
}
/// A felhasználói felületen megnyomták a gombot
bool eventHandler(const SDL_Event& ev) {
if (ev.type == SDL_MOUSEBUTTONDOWN) {
if (ev.button.button == SDL_BUTTON_RIGHT)
cb(ev, val);
return true;
}
return false;
}
void draw() const {}
};
#endif // ACTIVEBG_H
/**
* \file appshell.cpp
* \brief AppShell osztály tagfüggvényeinek megvalósítása
*
* \bug Érintőképernyőn SDL 1.2-vel az érintésből származó pozíció rossz. 1.3-as változatban ez már javítva van.
*/
#include "appshell.h"
#include "memtrace.h"
/// Eseményhurok.
/// Adminisztrálja az egér mozgását.
/// Minden, a tárolóban levő objektumra megnézi, hogy az esemény érinti-e az objektumot.
/// Ha igen, akkor meghívja az objektum eseménykezelőjét.
/// A tárolással fordított sorrendben keres, így a később betett objektum van "felül".
/// Az objektum eseménykezelője ettől még dönthet úgy, hogy nem kezeli.
/// Kihasználható, hogy az eseménykezelő meghívása előtt mindig van contains hívás.
void AppShell::mainLoop() {
SDL_Flip(scr);
SDL_Event ev;
Point cursor;
while (SDL_WaitEvent(&ev) && ev.type != SDL_QUIT) {
bool changed = false;
if (ev.type == SDL_MOUSEMOTION) { // egérmozgás követése
cursor.x = ev.motion.x;
cursor.y = ev.motion.y;
}
size_t i = widgets.size()-1;
while (i >= 0 && i < widgets.size()) { // a méret megváltozhat a ciklusban !
if (widgets[i]->contains(cursor)) { // ha a widget területére esik
if (widgets[i]->eventHandler(ev)) { // akkor elküldi az eseményt
changed = true; // megjegyzi, hogy változhatott a rajz
break;
}
}
i--;
}
if (changed) { // ha változhatott a rajz, frissíti a képernyőt
draw();
SDL_Flip(scr);
}
}
}
/**
* \file appshell.h
* \brief AppShell osztály deklarációja
*
*/
#ifndef APPSHELL_H
#define APPSHELL_H
#include "container.h"
/// Az eseményhurokért, valamint az SDL és az alkalmazás kapcsolatáért felelős.
/// Widget konténerként tárolja a fő widgetpéldányokat.
struct AppShell : public Container {
/// @param scr - SDL screen pointere
AppShell(SDL_Surface *scr) {
Widget::setSurface(scr);
}
/// maninLoop
/// Olvassa az eseményeket és meghívja a megfelelő eseménykezelő függvényt
void mainLoop();
};
#endif // APPSHELL_H
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="SDL_bboard" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/SDL_bboard" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
<Add option="-DMEMTRACE" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/SDL_bboard" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="0" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add directory="$(#sdl.include)" />
</Compiler>
<Linker>
<Add library="mingw32" />
<Add library="SDLmain" />
<Add library="SDL.dll" />
<Add library="user32" />
<Add library="gdi32" />
<Add library="winmm" />
<Add library="dxguid" />
<Add library="SDL_gfx" />
<Add library="SDL_image" />
<Add library="SDL_ttf" />
<Add directory="$(#sdl.lib)" />
</Linker>
<Unit filename="activebg.h" />
<Unit filename="appshell.cpp" />
<Unit filename="appshell.h" />
<Unit filename="bboard.h" />
<Unit filename="button.h" />
<Unit filename="circle.cpp" />
<Unit filename="circle.h" />
<Unit filename="color.h" />
<Unit filename="container.cpp" />
<Unit filename="container.h" />
<Unit filename="main.cpp" />
<Unit filename="memtrace.cpp" />
<Unit filename="memtrace.h" />
<Unit filename="point.h" />
<Unit filename="widget.cpp" />
<Unit filename="widget.h" />
<Extensions>
<code_completion />
<debugger />
<envvars />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* \file bboard.h
* \brief Bboard osztály deklarációja
*
*/
#ifndef BBOARD_H
#define BBOARD_H
#include "Container.h"
/// Egy konkrét Widget konténer.
/// Hazudós, mert minden koordinátát magáénak gondol.
/// Így meghívódik az eseménykezelője, ami nem más, mint a
/// Container eseménykezelője.
/// Itt lehetne ablakhoz rendelni.
class Bboard : public Container {
public:
/// Mivel igazi ablak nincs, a teljes képernyő a tárolóhoz tartozik.
/// Minden pontot magáénak tekint.
bool contains(const Point& p) {
Container::contains(p);
return true;
}
};
#endif // BBOARD_H
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="13.2">
<zoom_level>10</zoom_level>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>80</x>
<y>320</y>
<w>330</w>
<h>220</h>
</coordinates>
<panel_attributes>Container
--
- widgets: vector&lt;Widget*&gt;
- cursor: Point
--
+ add(Widget*): void
+ clear(): void
+ contains(Point&amp;): bool
+ eventHandler(SDL_Event&amp;): bool
+ draw(): void</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>0</x>
<y>90</y>
<w>210</w>
<h>300</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>80;280;30;280;30;30;190;30</additional_attributes>
</element>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>190</x>
<y>0</y>
<w>390</w>
<h>280</h>
</coordinates>
<panel_attributes>/Widget/
--
_# scr: SDL_Surface*_
# p0: Point
# fg: Color
# bg: Clolor
--
+ setSurface(SDL_Surface*): void
+ virtual contains(Point&amp;): bool
+ virtual eventHandler(SDL_Event&amp;): bool
+ move(): void
/+ virtual draw(): void/
</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>200</x>
<y>250</y>
<w>140</w>
<h>90</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;-</panel_attributes>
<additional_attributes>120;30;30;70</additional_attributes>
</element>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>430</x>
<y>320</y>
<w>330</w>
<h>170</h>
</coordinates>
<panel_attributes>Circle
--
- r: int
- fill: bool
--
+ contains(Point&amp;): bool
+ eventHandler(SDL_Event&amp;): bool
+ draw(): void</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>440</x>
<y>250</y>
<w>160</w>
<h>90</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;-</panel_attributes>
<additional_attributes>30;30;140;70</additional_attributes>
</element>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>340</x>
<y>580</y>
<w>220</w>
<h>100</h>
</coordinates>
<panel_attributes>AppShell
--
- scr: SDL_Surface
--
+ mainLoop()</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>220</x>
<y>510</y>
<w>260</w>
<h>90</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;-</panel_attributes>
<additional_attributes>30;30;240;70</additional_attributes>
</element>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>40</x>
<y>580</y>
<w>250</w>
<h>70</h>
</coordinates>
<panel_attributes>Bboard
--
--
+ contains(Point&amp;): bool</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>130</x>
<y>510</y>
<w>100</w>
<h>90</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;-</panel_attributes>
<additional_attributes>80;30;30;70</additional_attributes>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>420</x>
<y>680</y>
<w>350</w>
<h>140</h>
</coordinates>
<panel_attributes>template=T
Button
--
cb: T&amp;
val: int
--
+ eventHandler(SDL_Event&amp;): bool</panel_attributes>
<additional_attributes/>
</element>
<element>
<type>com.baselet.element.old.element.Relation</type>
<coordinates>
<x>600</x>
<y>460</y>
<w>90</w>
<h>260</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;-</panel_attributes>
<additional_attributes>30;30;70;240</additional_attributes>
</element>
<element>
<type>com.baselet.element.old.element.Class</type>
<coordinates>
<x>40</x>
<y>700</y>
<w>300</w>
<h>150</h>
</coordinates>
<panel_attributes>Bpanel
--
- bb: Bboard&amp;
- r: int
- c: color
--
+ operator()(SDL_Event&amp;, int)</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>330</x>
<y>750</y>
<w>110</w>
<h>30</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>90.0;10.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>170</x>
<y>640</y>
<w>30</w>
<h>80</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
</element>
</diagram>
/**
* \file button.h
* \brief Button osztály deklarációja
*
*/
#ifndef BUTTON_H
#define BUTTON_H
#include "circle.h"
/// Egy olyan kör, amire a callback függvény tehető.
/// A gomb "megnyomására" meghívódik a paraméterként kapott
/// osztály függvényhívás operátora a beállított int paraméterrel.
/// Azért template, hogy könnyebben alkalmazkodjon a különféle
/// callback függvényekhez, funktorokhoz.
template<class T = void (&)(const SDL_Event&, int) >
class Button : public Circle {
T& cb; ///< callback objektum referencia
int val; ///< int érték
public:
/// Konstruktor elteszi a callback rutin címét és a híváskor
/// átadandó int paramétert
Button(const Point& p0, int r, T& cb, int val = 0,
const Color& fg = WHITE, const Color& bg = BLACK) :
Circle(p0, r, fg, bg, true), cb(cb), val(val) { }
/// A felhasználói felületen megnyomták a gombot
bool eventHandler(const SDL_Event& ev) {
if (ev.type == SDL_MOUSEBUTTONDOWN) {
if (ev.button.button == SDL_BUTTON_LEFT)
cb(ev, val);
return true;
}
return Circle::eventHandler(ev);
}
};
#endif // BUTTON_H
/**
* \file circle.cpp
* \brief Circle osztály tagfüggvényeinek megvalósítása
*/
#include "circle.h"
#include "memtrace.h"
/// Kört rajzoló fv.
void Circle::draw() const {
if (fill) {
filledCircleColor(scr, p0.x, p0.y, r, fg);
circleColor (scr, p0.x, p0.y, r, fg);
} else {
filledCircleColor (scr, p0.x, p0.y, r, bg);
circleColor (scr, p0.x, p0.y, r, fg);
}
}
// Körlap egy pontját tesztelő fv.
bool Circle::contains(const Point& p) {
return r >= p0.distance(p); // sugáron belül esik
}
/// esemény
bool Circle::eventHandler(const SDL_Event& ev) {
if (ev.type == SDL_MOUSEBUTTONDOWN) { // kitöltés változik
if (ev.button.button == SDL_BUTTON_LEFT) {
fill = !fill;
draw();
}
return true;
} else if (ev.type == SDL_MOUSEMOTION && ev.motion.state) { // drag
move(Point(ev.motion.xrel, ev.motion.yrel));
return true;
}
return false;
}
/**
* \file Circle.h
* \brief Circle osztály deklarációja
*/
#ifndef CIRCLE_H
#define CIRCLE_H
#include "widget.h"
/// Kör osztály.
/// Eseménykezelője kezeli a gombnyomást, ami a kitöltést váltja.
/// Kezeli továbbá a húzást (drag). Ekkor meghívja a Widget move tagfüggvényét.
class Circle : public Widget {
int r; ///< sugár
bool fill; ///< kitöltött-e a kör
public:
/// Konstruktor
/// @param p0 - kezdőpont
/// @param r - sugár
/// @param sz - szín és átlátszóság
Circle(const Point& p0, int r,
const Color& fg = WHITE, const Color& bg = BLACK, bool fill = false)
:Widget(p0, fg, bg), r(r), fill(fill) // ősosztály + adattagok inic
{}
/// kört rajzol
void draw() const;
/// belül van-e
bool contains(const Point& p);
/// esemény
bool eventHandler(const SDL_Event& ev);
~Circle() {
fg = bg; // rajzolási szín legyen a háttér színe
draw(); // letörlés
}
};
#endif // CIRCLE_H
/**
* \file color.h
* \brief Color osztály deklarációja
*/
#ifndef COLOR_H
#define COLOR_H
/// Az egyszerűség kedvéért minden tagja publikus.
/// Így nem kell getter/setter.
struct Color {
Uint8 r, g, b; ///< RGB
Uint8 a; ///< átlátszóság
/// @param r - red
/// @param g - green
/// @param b - blue
/// @param a - transparency
Color(Uint8 r = 0, Uint8 g = 0, Uint8 b = 0, Uint8 a = 255)
:r(r), g(g), b(b), a(a) {}
/// cast Uint32-re
operator Uint32() const { return (r << 24) + (g << 16) + (b << 8) + a; }
};
/// Színkontsansok
const Color BLACK(0,0,0);
const Color WHITE(255,255,255);
const Color RED(255,0,0);
const Color GREEN(0,255,0);
const Color BLUE(0,0,255);
const Color BACKGND = BLACK;
#endif // COLOR_H
/**
* \file container.cpp
* \brief Container osztály függvényeinek megvalósítása
*/
#include "container.h"
#include "memtrace.h"
// Új widgetet ad a tárolóhoz
void Container::add(Widget *w) {
widgets.push_back(w);
w->draw();
}
// Törli a tárolót
void Container::clear() {
for (size_t i = 0; i < widgets.size(); i++)
delete widgets[i];
widgets.clear();
}
// Tárolóban levő minden elemre meghívja a rajzolót
void Container::draw() const {
for (size_t i = 0; i < widgets.size(); i++)
widgets[i]->draw();
}
// Eseménykezelés
bool Container::eventHandler(const SDL_Event& ev) {
for (size_t i = widgets.size()-1; i >= 0 && i < widgets.size(); i--) { // a méret megváltozhat a ciklusban !
if (widgets[i]->contains(cursor)) { // ha a területére esik
if (widgets[i]->eventHandler(ev)) // akkor elküldi az eseményt
return true;
}
}
return false;
}
/**
* \file container.h
* \brief Container osztály deklarációja
*/
#ifndef CONTAINER_H
#define CONTAINER_H
#include "widget.h"
#include <vector>
/// Általános widget konténer (heterogén kollekció).
class Container : public Widget {
protected:
std::vector<Widget*> widgets; ///< Itt tároljuk a pointereket
Point cursor; ///< egérmozgás követésére
public:
/// add
/// widget hozzáadása a konténerhez
/// @param w - widget pointere
void add(Widget *w);
/// clear
/// Minden tárolt tartalmazott objektumot eldob és megszüntet
void clear();
/// contains
/// Elteszi a pozíciót, mert a hívást követi az esemény kezelése.
/// @param p - adott pont
/// @return false
bool contains(const Point& p) {
cursor = p; // egérmozgás követése
return false; // nem tudjuk a használatot, ezért inkább false
}
/// Widget eseménykezelője.
/// Minden tartalamzott objektumot végigkérdez.
/// @param ev - SDL eseménystruktúra
/// @return true, ha lekezelte az eseményt. false, ha továbbadja a hívónak a kezelést
bool eventHandler(const SDL_Event&);
/// Minden tartalmazott osztály rajzoló funkcióját meghívja.
void draw() const;
/// destruktor
~Container() { clear(); }
};
#endif // CONTAINER_H
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* \file main.cpp
* \brief Egyszerű demo az SDL-lel kombinált Widget osztályok kipróbálására.
* \mainpage
* \par Demonstrációs cél:
* - callback technika bemutatása
* - eseményvezérlés
* - a grafikus felhasználói felület eseményvezérelt működése
* - egyszerű SDL grafika
* - újrafelhasználható elemek
* \par Specifikáció:
* Eseményekre reagáló alakzatok (körök) felrakása a képernyőre. Vezérlő gombok (töröl, kilép) kialakítása.
* \par Események:
* Egérmozgatás, kattintás, húzás (drag)
* \par Magyarázatok:
* Az SDL 1.x nem biztosít külön ablakokat. Minden egy ablakban van, ezért a Widget-ek is
* bárhol megjelenhetnek ebben. A Widget-ek felrakási sorrendben "takarják" egymást, de tényleges
* felülettel csak a körök rendelkeznek. A Bulletinboard (Bboard) háttere "átlátszó". Ezért elsőnek az
* ActiveBg nevű Widget-et tesszük fel. Ezután a nyomógombokat, majd a Bulletinboard-ot.
* Az ActiveBg "elkapja" a hozzá eljutó egérgomb eseményt és meghívja a hozzárendelt
* függvényt.
* Mivel a nyomógombok belső állapotokat változtatnak a nyomógombokhoz rendelt funkciókat (kivéve quit)
* a Bbpanel osztály valósítja meg, ami az állapotot tárolja. Ennek azonban csak egy belépési pontja van, a
* függvényhívás operátor, ezért a funkcióválasztást egy int paraméter segíti.
* \par Érdekesség:
* Osztály tagfüggvényét önállóan nem lehet függvéynpointerrel meghívni, hiszen a híváshoz egy \em this is kell.
* Ezért nem lehet a quit függvényhez hasonlóan egy osztály tagfüggvényét meghívni.
* \par UML
* \image html bboard.png "Az UMLet programmal rajzolt osztálydiagram" height=5
* Ez nem mindenben egyezik meg a Doxygen által generált ábrával. Az ábráról lemaradt az ActiveBg template, ami
* A Button sablonhoz hasonló, csak hazudósabb, és nincs grafikus reprezentációja.
*
* http://www.umlet.com/
*
*
*/
#include <iostream>
#include "appshell.h"
#include "bboard.h"
#include "button.h"
#include "activebg.h"
#include "memtrace.h"
/// segédfüggvény az SDL inicializálásához
/// @return surface pointer vagy 0
SDL_Surface* init() {
if (SDL_Init( SDL_INIT_VIDEO ) < 0)
return NULL;
/// SDL jelen változata lezárja a szabványos kimeneteteket és fájlba ír.
/// Ezért újra kinyitjuk
std::freopen( "CON", "w", stdout );
std::freopen( "CON", "w", stderr );
return SDL_SetVideoMode(1024, 768, 0, SDL_ANYFORMAT);
}
/// Bulletinboard kezelő panelje
class Bbpanel {
Bboard& bb; ///< ref. a táblára
int r; ///< kirajzolandó kör sugara
Color c; ///< kor színe
void chcolor() {
c.r += 50; c.g -= 50; c.b -= 10;
}
public:
static const int RIGTH_ON_BG = 0;
static const int ADD_CIRCLE = 1;
static const int CLEAR = 3;
// Konstruktor átveszi a táblát, és inicializálja a sugarat és színt
Bbpanel(Bboard& bb) :bb(bb), r(200), c(WHITE) {}
// ez az általános callback fv.
void operator()(const SDL_Event& ev, int fn) {
if (fn == RIGTH_ON_BG) {
// jobb gomb a háttéren
bb.add(new Circle(Point(ev.button.x, ev.button.y), 20, c));
chcolor();
} else if (fn == ADD_CIRCLE) {
// kör hozzáadása gomb
bb.add(new Circle(Point(350, 350), r, c));
chcolor();
r -= 10;
if (r <= 0) {
r = 200; c = WHITE;
}
} else if (fn == CLEAR) {
// clear gomb
bb.clear();
}
}
};
/// Kilépés, üzen saját magának
void quit(const SDL_Event&, int) {
SDL_Event ev;
ev.type = SDL_QUIT;
SDL_PushEvent(&ev);
}
int main(int argc, char** argv) {
{
SDL_Surface* screen = init();
if (screen == NULL) {
std::cerr << "Nem sikerult az SDL INIT: " << SDL_GetError() << std::endl;
return 1;
}
// Application shell létrehozása
AppShell app(screen);
Bboard* bb = new Bboard; // Bulletinboard
// Bbpanel olyan osztály, ami segít a gombokat kezelni.
Bbpanel panel(*bb); // ismernie kell a Bulletinboard-ot
// Először feltesszük az aktív hátteret (ez kap utoljára eseményt)
app.add(new ActiveBg<Bbpanel>(panel, Bbpanel::RIGTH_ON_BG)); // jobb gomb a háttéren
app.add(bb); // rátesszük a bulletinboard-ot
// Feltesszük a gombokat
app.add(new Button<Bbpanel>(Point(100, 60), 40, panel, Bbpanel::ADD_CIRCLE, GREEN)); // add circle
app.add(new Button<Bbpanel>(Point(300, 60), 30, panel, Bbpanel::CLEAR, RED)); // clear BB
app.add(new Button<>(Point(500, 60), 20, quit)); // quit
// eseményhurok
app.mainLoop();
SDL_Quit();
} /// memtrace miatt minden egy belső blokkban van.
return memtrace::mem_check(); /// SDL kilépésekor már nem tud kiírni.
}
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.
mem_dump: 2016.
*********************************/
/*definialni kell, ha nem paracssorbol allitjuk be (-DMEMTRACE) */
/*#define MEMTRACE */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#ifdef MEMTRACE
#define FROM_MEMTRACE_CPP
#include "memtrace.h"
#define FMALLOC 0
#define FCALLOC 1
#define FREALLOC 2
#define FFREE 3
#define FNEW 4
#define FDELETE 5
#define FNEWARR 6
#define FDELETEARR 7
#define COMP(a,d) (((a)<=3 && (d)<=3) || ((d)==(a)+1))
#define PU(p) ((char*)p+CANARY_LEN) // mem pointerbol user poi
#define P(pu) ((char*)pu-CANARY_LEN) // user pointerbol mem poi
#define XSTR(s) STR(s)
#define STR(s) #s
/*******************************************************************/
/* Segedfuggvenyek es egyebek */
/*******************************************************************/
START_NAMESPACE
static FILE *fperror = stderr;
#ifdef MEMTRACE_TO_MEMORY
static const unsigned int CANARY_LEN = 64;
#else
static const unsigned int CANARY_LEN = 0;
#endif
static const unsigned char canary_byte1 = 'k';
static const unsigned char canary_byte2 = 'K';
static unsigned char random_byte;
typedef enum {FALSE,TRUE} BOOL;
static const char * pretty[] = {"malloc(", "calloc(", "realloc(", "free(",
"new", "delete", "new[]", "delete[]"};
static const char * basename(const char * s) {
const char *s1,*s2;
s1 = strrchr(s,'/');
if(s1==NULL) s1 = s; else s1++;
s2 = strrchr(s1, '\\');
if(s2==NULL) s2 = s1; else s2++;
return s2;
}
static char *StrCpy(char ** to, const char * from) {
if(from == NULL) {
*to = NULL;
} else {
*to = (char*)malloc(strlen(from)+1);
if(*to) strcpy(*to, from);
}
return *to;
}
static void *canary_malloc(size_t size, unsigned char data) {
char *p = (char *)malloc(size+2*CANARY_LEN);
if (p) {
memset(p, canary_byte1, CANARY_LEN);
memset(p+CANARY_LEN, data, size);
memset(p+CANARY_LEN+size, canary_byte2, CANARY_LEN);
}
return p;
}
static int chk_canary(void *p, size_t size) {
unsigned char *pc = (unsigned char*)p;
unsigned int i;
for (i = 0; i < CANARY_LEN; i++)
if (pc[i] != canary_byte1)
return -1;
pc += CANARY_LEN+size;
for (i = 0; i < CANARY_LEN; i++)
if (pc[i] != canary_byte2)
return 1;
return 0;
}
typedef struct {
int f; /* allocator func */
int line;
char * par_txt;
char * file;
} call_t;
static call_t pack(int f, const char * par_txt, int line, const char * file) {
call_t ret;
ret.f = f;
ret.line = line;
StrCpy(&ret.par_txt, par_txt);
StrCpy(&ret.file, file);
return ret;
}
static void print_call(const char * msg, call_t call) {
if(msg) fprintf(fperror, "%s", msg);
fprintf(fperror, "%s", pretty[call.f]);
fprintf(fperror, "%s", call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(fperror, ")");
fprintf(fperror," @ %s:", call.file ? basename(call.file) : "?");
fprintf(fperror,"%d\n",call.line ? call.line : 0);
}
/* memoriateruletet dump */
static void dump_memory(void const *mem, size_t size, size_t can_len) {
unsigned char const *m=(unsigned char const *) mem;
unsigned int s, o;
if (can_len > 0)
fprintf(fperror, "Dump (addr: %p kanari hossz: %d):\n", m+can_len, can_len);
else
fprintf(fperror, "Dump: (addr: %p) \n", m);
size += 2*can_len;
for (s = 0; s < (size+15)/16; s++) {
fprintf(fperror, "%04x:%c ", s*16, s*16 < can_len || s*16 >= size-can_len ? ' ' : '*');
for (o = 0; o < 16; o++) {
if (o == 8) fprintf(fperror, " ");
if (s*16+o < size)
fprintf(fperror, "%02x ", m[s*16+o]);
else
fprintf(fperror, " ");
}
fprintf(fperror, " ");
for (o = 0; o < 16; o++) {
if (s*16+o < size)
fprintf(fperror, "%c", isprint(m[s*16+o]) ? m[s*16+o] : '.');
else
fprintf(fperror, " ");
}
fprintf(fperror, "\n");
}
}
void mem_dump(void const *mem, size_t size) {
dump_memory(mem, size, 0);
}
static BOOL dying;
static void die(const char * msg, void * p, size_t size, call_t * a, call_t * d) {
#ifdef MEMTRACE_ERRFILE
fperror = fopen(XSTR(MEMTRACE_ERRFILE), "w");
#endif
fprintf(fperror,"%s\n",msg);
if (p) {
fprintf(fperror, "\tPointer:\t%p", PU(p));
if (size) fprintf(fperror," (%u byte)", (unsigned)size);
fprintf(fperror,"\n");
}
if (a) print_call("\tFoglalas:\t", *a);
if (d) print_call("\tFelszabaditas:\t", *d);
if (p) dump_memory(p, size, CANARY_LEN);
dying = TRUE;
exit(120);
}
static void initialize();
END_NAMESPACE
/*******************************************************************/
/* MEMTRACE_TO_MEMORY */
/*******************************************************************/
#ifdef MEMTRACE_TO_MEMORY
START_NAMESPACE
typedef struct _registry_item {
void * p; /* mem pointer*/
size_t size; /* size*/
call_t call;
struct _registry_item * next;
} registry_item;
static registry_item registry; /*sentinel*/
static void print_registry_item(registry_item * p) {
if (p) {
print_registry_item(p->next);
fprintf(fperror, "\t%p%5u byte ",p->p, (unsigned)p->size);
print_call(NULL, p->call);
if(p->call.par_txt) free(p->call.par_txt);
if(p->call.file) free(p->call.file);
free(p);
}
}
int mem_check(void) {
initialize();
if(dying) return 2;
if(registry.next) {
/*szivarog*/
#ifdef MEMTRACE_ERRFILE
fperror = fopen(XSTR(MEMTRACE_ERRFILE), "w");
#endif
fprintf(fperror, "Szivargas:\n");
print_registry_item(registry.next);
registry.next = NULL;
return 1;
}
return 0;
}
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY*/
/*******************************************************************/
/* MEMTRACE_TO_FILE */
/*******************************************************************/
#ifdef MEMTRACE_TO_FILE
START_NAMESPACE
static FILE * trace_file;
END_NAMESPACE
#endif
/*******************************************************************/
/* register/unregister */
/*******************************************************************/
START_NAMESPACE
static BOOL register_memory(void * p, size_t size, call_t call) {
initialize();
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file, "%p\t%d\t%s%s", PU(p), size, pretty[call.f], call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(trace_file, ")");
fprintf(trace_file, "\t%d\t%s\n", call.line, call.file ? call.file : "?");
fflush(trace_file);
#endif
#ifdef MEMTRACE_TO_MEMORY
{/*C-blokk*/
registry_item * n = (registry_item*)malloc(sizeof(registry_item));
if(n==NULL) return FALSE;
n->p = p;
n->size = size;
n->call = call;
n->next = registry.next;
registry.next = n;
}/*C-blokk*/
#endif
return TRUE;
}
#ifdef MEMTRACE_TO_MEMORY
static registry_item *find_registry_item(void * p) {
registry_item *n = &registry;
for(; n->next && n->next->p != p ; n=n->next);
return n;
}
#endif
static void unregister_memory(void * p, call_t call) {
initialize();
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file, "%p\t%d\t%s%s", PU(p), -1, pretty[call.f], call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(trace_file, ")");
fprintf(trace_file,"\t%d\t%s\n",call.line, call.file ? call.file : "?");
fflush(trace_file);
#endif
#ifdef MEMTRACE_TO_MEMORY
{ /*C-blokk*/
registry_item * n = find_registry_item(p);
if(n->next) {
registry_item * r = n->next;
n->next = r->next;
if(COMP(r->call.f,call.f)) {
int chk = chk_canary(r->p, r->size);
if (chk < 0)
die("Blokk elott serult a memoria:", r->p,r->size,&r->call,&call);
if (chk > 0)
die("Blokk utan serult a memoria", r->p,r->size,&r->call,&call);
/*rendben van minden*/
if(call.par_txt) free(call.par_txt);
if(r->call.par_txt) free(r->call.par_txt);
if(call.file) free(call.file);
if(r->call.file) free(r->call.file);
free(r);
} else {
/*hibas felszabaditas*/
die("Hibas felszabaditas:",r->p,r->size,&r->call,&call);
}
} else {
die("Nem letezo adat felszabaditasa:", p, 0,NULL,&call);
}
} /*C-blokk*/
#endif
}
END_NAMESPACE
/*******************************************************************/
/* C-stlus memriakezels */
/*******************************************************************/
#ifdef MEMTRACE_C
START_NAMESPACE
void * traced_malloc(size_t size, const char * par_txt, int line, const char * file) {
void * p;
initialize();
p = canary_malloc(size, random_byte);
if (p) {
if(!register_memory(p,size,pack(FMALLOC,par_txt,line,file))) {
free(p);
return NULL;
}
return PU(p);
}
return NULL;
}
void * traced_calloc(size_t count, size_t size, const char * par_txt, int line, const char * file) {
void * p;
initialize();
size *= count;
p = canary_malloc(size, 0);
if(p) {
if(!register_memory(p,size,pack(FCALLOC,par_txt,line,file))) {
free(p);
return NULL;
}
return PU(p);
}
return NULL;
}
void traced_free(void * pu, const char * par_txt, int line, const char * file) {
initialize();
if(pu) {
unregister_memory(P(pu), pack(FFREE,par_txt,line,file));
free(P(pu));
} else {
/*free(NULL) eset*/
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file,"%s\t%d\t%10s\t","NULL",-1,pretty[FFREE]);
fprintf(trace_file,"%d\t%s\n",line,file ? file : "?");
fflush(trace_file);
#endif
#ifndef ALLOW_FREE_NULL
{/*C-blokk*/
call_t call;
call = pack(FFREE,par_txt,line,file);
die("free(NULL) hivasa:",NULL,0,NULL,&call);
}/*C-blokk*/
#endif
}
}
void * traced_realloc(void * old, size_t size, const char * par_txt, int line, const char * file) {
void * p;
size_t oldsize = 0;
registry_item * n;
initialize();
#ifdef MEMTRACE_TO_MEMORY
n = find_registry_item(P(old));
if (n) oldsize = n->next->size;
p = canary_malloc(size, random_byte);
#else
p = realloc(old, size);
#endif
if (p) {
/*Ha sikerult a foglalas, regisztraljuk*/
register_memory(p,size,pack(FREALLOC, par_txt, line,file));
if (old) {
#ifdef MEMTRACE_TO_MEMORY
int cpsize = 2*CANARY_LEN;
if (oldsize < size) cpsize += oldsize;
else cpsize += size;
memcpy(p, P(old), cpsize);
#endif
unregister_memory(P(old), pack(FREALLOC, par_txt, line, file));
#ifdef MEMTRACE_TO_MEMORY
free P(old);
#endif
}
return PU(p);
} else {
return NULL;
}
}
END_NAMESPACE
#endif/*MEMTRACE_C*/
/*******************************************************************/
/* C++-stlus memriakezels */
/*******************************************************************/
#ifdef MEMTRACE_CPP
START_NAMESPACE
std::new_handler _new_handler;
void _set_new_handler(std::new_handler h) {
initialize();
_new_handler = h;
}
static call_t delete_call;
static BOOL delete_called;
void set_delete_call(int line, const char * file) {
initialize();
delete_call=pack(0,"",line,file); /*func rtke lnyegtelen, majd fellrjuk*/
delete_called = TRUE;
}
void * traced_new(size_t size, int line, const char * file, int func) {
initialize();
for (;;) {
void * p = canary_malloc(size, random_byte);
if(p) {
register_memory(p,size,pack(func,"",line,file));
return PU(p);
}
if (_new_handler == 0)
throw std::bad_alloc();
_new_handler();
}
}
void traced_delete(void * pu, int func) {
initialize();
if(pu) {
/*kiolvasom call-t, ha van*/
memtrace::call_t call = delete_called ? (delete_call.f=func, delete_call) : pack(func,NULL,0,NULL);
memtrace::unregister_memory(P(pu),call);
free(P(pu));
}
delete_called=FALSE;
}
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC {
return memtrace::traced_new(size,line,file,FNEW);
}
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC {
return memtrace::traced_new(size,line,file,FNEWARR);
}
void * operator new(size_t size) THROW_BADALLOC {
return memtrace::traced_new(size,0,NULL,FNEW);
}
void * operator new[](size_t size) THROW_BADALLOC {
return memtrace::traced_new(size,0,NULL,FNEWARR);
}
void operator delete(void * p) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
void operator delete[](void * p) THROW_NOTHING {
memtrace::traced_delete(p,FDELETEARR);
}
#endif/*MEMTRACE_CPP*/
/*******************************************************************/
/* initialize */
/*******************************************************************/
START_NAMESPACE
static void initialize() {
static BOOL first = TRUE;
if(first) {
fperror = stderr;
random_byte = (unsigned char)time(NULL);
first = FALSE;
dying = FALSE;
#ifdef MEMTRACE_TO_MEMORY
registry.next = NULL;
#if !defined(USE_ATEXIT_OBJECT) && defined(MEMTRACE_AUTO)
atexit((void(*)())mem_check);
#endif
#endif
#ifdef MEMTRACE_TO_FILE
trace_file = fopen("memtrace.dump","w");
#endif
#ifdef MEMTRACE_CPP
_new_handler = NULL;
delete_called = FALSE;
delete_call = pack(0,NULL,0,NULL);
#endif
}
}
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
int atexit_class::counter = 0;
#endif
END_NAMESPACE
#endif
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.,
mem_dump: 2016.
*********************************/
#ifndef MEMTRACE_H
#define MEMTRACE_H
#if defined(MEMTRACE)
/*ha definilva van, akkor a hibakat ebbe a fajlba rja, egybkent stderr-re*/
/*#define MEMTRACE_ERRFILE MEMTRACE.ERR*/
/*ha definialva van, akkor futas kozben lancolt listat epit. Javasolt a hasznalata*/
#define MEMTRACE_TO_MEMORY
/*ha definialva van, akkor futas kozben fajlba irja a foglalasokat*/
/*ekkor nincs ellenorzes, csak naplozas*/
/*#define MEMTRACE_TO_FILE*/
/*ha definialva van, akkor a megallaskor automatikus riport keszul */
#define MEMTRACE_AUTO
/*ha definialva van, akkor malloc()/calloc()/realloc()/free() kovetve lesz*/
#define MEMTRACE_C
#ifdef MEMTRACE_C
/*ha definialva van, akkor free(NULL) nem okoz hibat*/
#define ALLOW_FREE_NULL
#endif
#ifdef __cplusplus
/*ha definialva van, akkor new/delete/new[]/delete[] kovetve lesz*/
#define MEMTRACE_CPP
#endif
#if defined(__cplusplus) && defined(MEMTRACE_TO_MEMORY)
/*ha definialva van, akkor atexit helyett objektumot hasznal*/
/*ajanlott bekapcsolni*/
#define USE_ATEXIT_OBJECT
#endif
/******************************************/
/* INNEN NE MODOSITSD */
/******************************************/
#ifdef NO_MEMTRACE_TO_FILE
#undef MEMTRACE_TO_FILE
#endif
#ifdef NO_MEMTRACE_TO_MEMORY
#undef MEMTRACE_TO_MEMORY
#endif
#ifndef MEMTRACE_AUTO
#undef USE_ATEXIT_OBJECT
#endif
#ifdef __cplusplus
#define START_NAMESPACE namespace memtrace {
#define END_NAMESPACE } /*namespace*/
#define TRACEC(func) memtrace::func
#include <new>
#else
#define START_NAMESPACE
#define END_NAMESPACE
#define TRACEC(func) func
#endif
/* A Visual Studio figyelmen kivul hagyja a "throw" deklaraciokat, a gcc -pedantic pedig igenyli.*/
#ifdef _MSC_VER
/* Ha studio */
#define THROW_BADALLOC
#define THROW_NOTHING
#else
/* Normalis forditok */
#define THROW_BADALLOC throw (std::bad_alloc)
#define THROW_NOTHING throw ()
#endif
#if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE
int mem_check(void);
END_NAMESPACE
#endif
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
START_NAMESPACE
class atexit_class {
private:
static int counter;
public:
atexit_class() {
counter++;
}
~atexit_class() {
if(--counter==0)
mem_check();
}
};
static atexit_class atexit_obj;
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY && USE_ATEXIT_OBJECT*/
/*Innentol csak a "normal" include eseten kell, kulonben osszezavarja a mukodest*/
#ifndef FROM_MEMTRACE_CPP
#include <stdlib.h>
#ifdef __cplusplus
#include <iostream>
/* ide gyjtjk a nemtrace-vel sszeakad headereket, hogy elbb legyenek */
#include <fstream> // VS 2013 headerjben van deleted definici
#endif
#ifdef MEMTRACE_CPP
namespace std {
typedef void (*new_handler)();
}
#endif
#ifdef MEMTRACE_C
START_NAMESPACE
#undef malloc
#define malloc(size) TRACEC(traced_malloc)(size,#size,__LINE__,__FILE__)
void * traced_malloc(size_t size, const char *size_txt, int line, const char * file);
#undef calloc
#define calloc(count,size) TRACEC(traced_calloc)(count, size, #count","#size,__LINE__,__FILE__)
void * traced_calloc(size_t count, size_t size, const char *size_txt, int line, const char * file);
#undef free
#define free(p) TRACEC(traced_free)(p, #p,__LINE__,__FILE__)
void traced_free(void * p, const char *size_txt, int line, const char * file);
#undef realloc
#define realloc(old,size) TRACEC(traced_realloc)(old,size,#size,__LINE__,__FILE__)
void * traced_realloc(void * old, size_t size, const char *size_txt, int line, const char * file);
void mem_dump(void const *mem, size_t size);
END_NAMESPACE
#endif/*MEMTRACE_C*/
#ifdef MEMTRACE_CPP
START_NAMESPACE
#undef set_new_handler
#define set_new_handler(f) TRACEC(_set_new_handler)(f)
void _set_new_handler(std::new_handler h);
void set_delete_call(int line, const char * file);
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new(size_t size) THROW_BADALLOC;
void * operator new[](size_t size) THROW_BADALLOC;
void operator delete(void * p) THROW_NOTHING;
void operator delete[](void * p) THROW_NOTHING;
#define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
#endif /*MEMTRACE_CPP*/
#endif /*FROM_MEMTRACE_CPP*/
#endif /*MEMCHECK*/
#endif /*MEMTRACE_H*/
/**
* \file point.h
* \brief Point osztály deklarációja
*/
#ifndef POINT_H
#define POINT_H
#include <cmath>
/// Az egyszerűség kedvéért minden tagja publikus.
/// Igy nem kell getter/setter.
/// Csak azok az operatorok lettek megvalósítva, melyeket használ a demo
struct Point {
int x;
int y;
Point(int x = 0, int y = 0) :x(x), y(y) {}
/// += operator
Point& operator+=(const Point& rhs_p) {
x += rhs_p.x;
y += rhs_p.y;
return *this;
}
/// - operator
Point operator-(const Point& rhs_p) const {
return Point(rhs_p.x-x, rhs_p.y-y);
}
/// távolság
double distance(Point p2) const {
p2 = *this - p2;
return sqrt(p2.x*p2.x+p2.y*p2.y);
}
};
#endif // POINT_H
/**
* \file widget.cpp
* \brief Widget osztály tagfüggvényeinek megvalósítása
*/
#include "widget.h"
#include "memtrace.h"
SDL_Surface* Widget::scr; ///< statikus tag létrehozása
/// move - eltolja a widget origóját
/// @param d - eltolás
void Widget::move(const Point& d) {
Color tsz = fg; // tényleges rajzolási szín elmentése
fg = bg; // rajzolási szín legyen a háttér színe
draw(); // letörlés az eredeti helyről
p0 += d; // mozgatás: a pozíció változik
fg = tsz; // rajzolási szín a tényleges szín
draw(); // felrajzolás az új pozícióra
}
/**
* \file widget.h
* \brief Widget alaposztály deklarációja
*/
#ifndef WIDGET_H
#define WIDGET_H
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include "point.h"
#include "color.h"
/// Absztrakt osztály.
/// Statikus tagként tárolja az SDL surface pointert.
/// Nem szép megoldás, de szebb mintha globális lenne.
class Widget {
protected:
static SDL_Surface *scr; ///< eldugott globális változó
Point p0; ///< Widget origója
Color fg; ///< Előtér szín
Color bg; ///< Háttérszín
public:
/// Konstruktor
/// @param p0 - referencia pont
Widget(const Point& p0 = Point(),
const Color& fg = WHITE,
const Color& bg = BLACK) :p0(p0), fg(fg), bg(bg) {}
/// suface beállítása
/// @param s - SDL surface
static void setSurface(SDL_Surface* s) { scr = s; }
/// contains
/// Egy adott pontról eldönti, hogy a widget területére esik-e
/// @param p - adott pont
/// @return true, ha a pont az widgeten belül van. false egyébként
virtual bool contains(const Point& p) { return false; }
/// Widget eseménykezelője
/// @param ev - SDL eseménystruktúra
/// @return true, ha lekezelte az eseményt. false, ha továbbadja a hívónak a kezelést
virtual bool eventHandler(const SDL_Event& ev) { return false; };
/// move: origóját eltolja az új pontba
/// @param d - eltolás vektora
void move(const Point& d);
/// draw
/// Felrajzolja a widgetet
/// Tipikusan az eseménykezelő hívja, de esetenként más is.
virtual void draw() const = 0; // tisztán virtuális
/// destruktor
virtual ~Widget() {}
};
#endif // WIDGET_H
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="ctor_dtor2" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/ctor_dtor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/ctor_dtor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-pedantic" />
<Add option="-Wall" />
<Add option="-Werror" />
</Compiler>
<Unit filename="ctor_dtor2.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* Egyszerű osztályhierarchia az ctor/dtor hívási sorrendjének bemutatására.
* Az azonos feladatok végrehajtási sorrendje (pl. adattagok konstruktorhívása,
* vagy ősosztályok konstruktorának hívási sorrendje) a deklaráció sorrendjétől
* függ.
*/
#include <iostream>
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
/**
Konstruktor:
* Öröklési lánc végén hívja a virtuális alaposztályok konstruktorait.
* Hívja a közvetlen, nem virtuális alaposztályok konstruktorait.
* Létrehozza a saját részt:
- beállítja a virtuális alaposztály mutatóit
- beállítja a virtuális függvények mutatóit
- hívja a tartalmazott objektumok konstruktorait
- végrehajtja a programozott törzset
*/
/**
Destruktor:
* Megszünteti a saját részt:
- végrehajtja a programozott törzset
- hívja a tartalmazott objektumok destruktorait
- beállítja a virtuális függvények mutatóit
- beállítja a virtuális alaposztály mutatóit
* Hívja a közvetlen, nem virtuális alaposztályok destruktorait.
* Öröklési lánc végén hívja a virtuális alaposztályok destruktorait.
*/
/// Virtuális alaposztályok
struct VirtAlap1 {
VirtAlap1() {
cout << "ctor: VirtAlap1" << endl;
}
~VirtAlap1() {
cout << "dtor: VirtAlap1" << endl;
}
};
struct VirtAlap2 {
VirtAlap2() {
cout << "ctor: VirtAlap2" << endl;
}
~VirtAlap2() {
cout << "dtor: VirtAlap2" << endl;
}
};
/// Nem virt alaposztályok
struct NemVirtAlap1 : virtual VirtAlap1, virtual VirtAlap2 {
NemVirtAlap1() {
cout << "ctor: NemVirtAlap1" << endl;
}
~NemVirtAlap1() {
cout << "dtor: NemVirtAlap1" << endl;
}
};
struct NemVirtAlap2 {
NemVirtAlap2() {
cout << "ctor: NemVirtAlap2" << endl;
}
~NemVirtAlap2() {
cout << "dtor: NemVirtAlap2" << endl;
}
};
/// Adattagok
struct Adat1 {
Adat1() { cout << "ctor: Adat1" << endl; }
~Adat1() { cout << "dtor: Adat1" << endl; }
};
struct Adat2 {
Adat2() { cout << "ctor: Adat2" << endl; }
~Adat2() { cout << "dtor: Adat2" << endl; }
};
/// Az OSZTALY
struct A : NemVirtAlap1, NemVirtAlap2 {
Adat1 adat1;
Adat2 adat2;
A() {
cout << "ctor: A" << endl;
}
~A() {
cout << "dtor: A" << endl;
}
};
int main() {
A* p = new A;
cin.ignore(100, '\n');
delete p;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment