Commit 1b9919ba by Szeberényi Imre

v0

parents
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="ctor_dtor" />
<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="-Wall" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="ctor_dtor.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* Egyszer osztlyhierarchia az ctor/dtor feladatainak bemutatshoz
* A pointerek tlltst csak kzvetve, az f() virtulis fggvnyen
* keresztl tudjuk megfigyelni, amit mindig a g() fggvny hv az alaposztlybl.
* A g() fggvnyt viszont minden konstruktorbl s destruktorbl meghvunk.
* gy Attl fggen, hogy az f() virt. fggvny pointere hova mutat,
* ms s ms f() vltozat futnak le.
*/
/**
* HA a DUMP makr definilt, akkor a g() fggvny az alaposztly
* memriakpt is kirja hexadecimlisan.
* FELTTELEZZK, hogy a memriakp elejn a virt. tbla mutatja ll.
* Ezt kvetik az adattagok. Az egyszersg kedvrt 3 db pointer az
* adattag amit 1,2,3 rtkkel tltnk fel.
*/
#define DUMP
#include <iostream>
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
/**
Konstruktor:
* rklsi lnc vgn hvja a virtulis alaposztlyok konstruktorait.
* Hvja a kzvetlen, nem virtulis alaposztlyok konstruktorait.
* Ltrehozza a sajt rszt:
- belltja a virtulis alaposztly mutatit
- belltja a virtulis fggvnyek mutatit
- hvja a tartalmazott objektumok konstruktorait
- vgrehajtja a programozott trzset
*/
/**
Destruktor:
* Megsznteti a sajt rszt:
- vgrehajtja a programozott trzset
- hvja a tartalmazott objektumok destruktorait
- belltja a virtulis fggvnyek mutatit
- belltja a virtulis alaposztly mutatit
* Hvja a kzvetlen, nem virtulis alaposztlyok destruktorait.
* rklsi lnc vgn hvja a virtulis alaposztlyok destruktorait.
*/
/// Virtulis alaposztly
struct VirtAlap {
int* adat[3]; /// dump miatt 3 db int*
VirtAlap() {
for (int i = 0; i < 3; i++) adat[i] = reinterpret_cast<int*>(i+1);
cout << "Oroklesi lanc vegen virt. alaposztaly konstruktor" << endl;
g("VirtAlap()");
}
~VirtAlap() {
cout << "Oroklesi lanc vegen alaposztaly destruktor" << endl;
g("~VirtAlap()");
}
void g(const char *honnan) {
cout << " " << honnan << "-bol hivjuk f()-et:";
f();
dump();
}
virtual void f() {
cout << " VirtAlap::f() vagyok" << endl;
}
/// p0 cmtl l darab int*-ot r ki
void dump(void*p0, int l) {
int **p = reinterpret_cast<int**>(p0);
for (int i = 0; i < l; i++)
cout << *p++ << " ";
cout << endl;
}
void dump() {
#ifdef DUMP
cout << " Alaposztaly memoriakepe: ";
dump(this, sizeof(VirtAlap)/sizeof(int*));
int* p = *reinterpret_cast<int**>(this);
cout << " Virt.fv. tabla tartalma: ";
dump(p, 2);
#endif
}
};
/// Kzvetlen nem virt alaposztly
struct KozvNemVirtAlap : virtual VirtAlap {
KozvNemVirtAlap() {
cout << "Kozvetlen nem virt. alaposztaly konstruktor" << endl;
g("KozvNemVirtAlap()");
}
~KozvNemVirtAlap() {
cout << "Kozvetlen nem virt. alaposztaly destruktor" << endl;
g("~KozvNemVirtAlap()");
}
void f() {
cout << " KozvNemVirtAlap::f() vagyok" << endl;
}
};
/// Adattag
struct Adat {
Adat() { cout << "Tartalmazott obj. konstruktor" << endl; }
~Adat() { cout << "Tartalmazott obj. destruktor" << endl; }
};
/// Az OSZTALY
struct A : KozvNemVirtAlap {
Adat adat;
A() {
cout << "Konstruktor programozott torzse" << endl;
g("A()");
}
~A() {
cout << "Destruktor programozott torzse" << endl;
g("~A()");
}
void f() {
cout << " A::f() vagyok" << endl;
}
};
int main() {
cout << "struct VirtAlap;\nstruct KozvNemVirtAlap : virtual VirtAlap;\n"
<< "struct A : KozvNemVirtAlap;\n"
<< "\nA* p = new A;\n\n";
A* p = new A;
cin.ignore(100, '\n');
cout << "delete p;\n\n";
delete p;
return 0;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="iroda" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/iroda" 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/iroda" 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="-std=c++11" />
<Add option="-Wfatal-errors" />
<Add option="-Wall" />
</Compiler>
<Unit filename="iroda.cpp" />
<Unit filename="iroda.h" />
<Unit filename="main.cpp" />
<Unit filename="memtrace.cpp" />
<Unit filename="memtrace.h" />
<Unit filename="string5.cpp" />
<Unit filename="string5.h" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
/**
* \file iroda.cpp
*
* Irodai hierarchiát megvalósító osztályok
*
*/
#include <iostream>
#include "iroda.h"
using std::cout;
using std::endl;
void Alkalmazott::kiir() const {
cout << nev << " fizetese: " << fizetes << endl;
}
void HatIdCsV::kiir() const {
CsopVez::kiir();
HatIdeju::kiir();
}
void HatIdCsVezH::kiir() const {
HatIdCsV::kiir();
cout << "Kit helyettesit: " << kit.getNev() << endl;
}
/**
* \file iroda.h
*
* Irodai hierarchiát megvalósító osztályok
*
*/
#ifndef IRODA_H
#define IRODA_H
//#define VIRT_OROKLESSEL
#ifdef VIRT_OROKLESSEL
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
#include <ctime>
#include "String5.h"
typedef int csop_t; // csoport típusa
/**
* Alkalmazott
*/
class Alkalmazott {
protected:
String nev; // név
double fizetes; // fizetés
public:
Alkalmazott(const char *n, double fiz) :nev(n), fizetes(fiz) {}
const char* getNev() const { return nev.c_str(); }
virtual void kiir() const;
};
/**
* Csopotvezetõ
*/
class CsopVez : VIRTUAL public Alkalmazott {
protected:
csop_t csoport; // csoport azon.
public:
CsopVez(const char *n, double f, csop_t cs)
:Alkalmazott(n, f), // alaposztály inicializálása
csoport(cs) // csoport inicializálás
{}
csop_t getcsoport() { // csoport lekérdezése
return csoport;
}
};
/**
* Határozott idejű alkalmazott
*/
class HatIdeju : VIRTUAL public Alkalmazott {
protected:
time_t ido; // szerződése lejár ekkor
public:
HatIdeju(const char *n, double f, time_t t)
:Alkalmazott(n, f), // alaposztály inicializálása
ido(t) // idő inicializálás
{}
};
/**
* Határozott idejű csoportvezetõ
*/
class HatIdCsV :public CsopVez, public HatIdeju {
public:
HatIdCsV(const char* n, double f, csop_t cs, time_t t) :
#ifdef VIRT_OROKLESSEL
Alkalmazott(n, f),
#endif
CsopVez(n, f*2, cs), // szándékosan más fizetést kap,
HatIdeju(n, f*10, t) // hogy látható legyen az adatduplikáció
{}
void kiir() const;
};
/**
* Határozott idejű csoportvezetõ helyettes
*/
class HatIdCsVezH :public HatIdCsV {
CsopVez& kit; // kit helyettesít.
// Gázos megoldás, ha elõbb megszűnik az, akire hivatkozik!
public:
HatIdCsVezH(HatIdCsV& kit, const char* n, double f, time_t t) :
#ifdef VIRT_OROKLESSEL
Alkalmazott(n, f),
#endif
HatIdCsV(n, f, kit.getcsoport(), t), // alaposztály
kit(kit) // kit helyettesít
{}
void kiir() const;
};
#endif // IRODA_H
<?xml version="1.0" encoding="windows-1250"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="iroda"
ProjectGUID="{96437249-9FD2-46D7-901D-29EC62966FDC}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/iroda.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/iroda.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/iroda.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\iroda.cpp">
</File>
<File
RelativePath=".\main.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\iroda.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
/**
* \file main.cpp
*
* Egyszerű program a diamond öröklés bajainak bemutatására
*
* Az iroda.h fájl elején levő VIRT_OROKLESSEL szimbólumtól függően
* virt.örökléssel, vagy anélkül fordul.
*
*/
#include "iroda.h"
int main() {
Alkalmazott lusta("Lusta Dick", 100);
HatIdeju grabo("Grabovszki", 300, 1000);
CsopVez gatto("Mr. Gatto ", 500, 1);
HatIdCsV tejfel("Mr. Tejfel", 600, 2, 1000);
HatIdCsVezH safra(tejfel, "Safranek", 700, 1000);
lusta.kiir();
grabo.kiir();
gatto.kiir();
tejfel.kiir();
safra.kiir();
return 0;
}
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.
VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016.
meset felszabaditaskor: 2018.
typo: 2019.
singleton: 2019.
*********************************/
/*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;
#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, FILE* fp) {
unsigned char const *m=(unsigned char const *) mem;
unsigned int s, o;
if (can_len > 0)
fprintf(fp, "Dump (addr: %p kanari hossz: %d):\n", m+can_len, (int)can_len);
else
fprintf(fp, "Dump: (addr: %p) \n", m);
size += 2*can_len;
for (s = 0; s < (size+15)/16; s++) {
fprintf(fp, "%04x:%c ", s*16, s*16 < can_len || s*16 >= size-can_len ? ' ' : '*');
for (o = 0; o < 16; o++) {
if (o == 8) fprintf(fp, " ");
if (s*16+o < size)
fprintf(fp, "%02x ", m[s*16+o]);
else
fprintf(fp, " ");
}
fprintf(fp, " ");
for (o = 0; o < 16; o++) {
if (s*16+o < size)
fprintf(fp, "%c", isprint(m[s*16+o]) ? m[s*16+o] : '.');
else
fprintf(fp, " ");
}
fprintf(fp, "\n");
}
}
void mem_dump(void const *mem, size_t size, FILE* fp) {
dump_memory(mem, size, 0, fp);
}
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," (%d byte)", (int)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, fperror);
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%5d byte ",p->p, (int)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);
}
}
/* ha nincs hiba, akkor 0-val tér vissza */
int mem_check(void) {
initialize();
if(dying) return 2; /* címzési hiba */
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; /* memória fogyás */
}
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 int allocated_blks;
int allocated_blocks() { return allocated_blks; }
static BOOL register_memory(void * p, size_t size, call_t call) {
initialize();
allocated_blks++;
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file, "%p\t%d\t%s%s", PU(p), (int)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) {
allocated_blks--;
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);
memset(PU(r->p), 'f', r->size);
PU(r->p)[r->size-1] = 0;
free(r);
} else {
/*hibas felszabaditas*/
die("Hibas felszabaditas:",r->p,r->size,&r->call,&call);
}
} else {
die("Nem letezo, vagy mar felszabaditott adat felszabaditasa:", p, 0,NULL,&call);
}
} /*C-blokk*/
#endif
}
END_NAMESPACE
/*******************************************************************/
/* C-stílusú memóriakezelés */
/*******************************************************************/
#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++-stílusú memóriakezelés */
/*******************************************************************/
#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 értéke lényegtelen, majd felülírjuk*/
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);
}
/* Visual C++ 2012 miatt kell, mert háklis, hogy nincs megfelelő delete, bár senki sem használja */
void operator delete(void * p, int, const char *) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
void operator delete[](void * p, int, const char *) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
#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(*)(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
}
}
END_NAMESPACE
#endif
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.,
VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016.
inclue-ok: 2017., 2018. 2019.
singleton: 2019.
*********************************/
#ifndef MEMTRACE_H
#define MEMTRACE_H
#if defined(MEMTRACE)
/*ha definiálva van, akkor a hibakat ebbe a fajlba írja, egyébkent 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
// THROW deklaráció változatai
#if defined(_MSC_VER)
// VS rosszul kezeli az __cplusplus makrot
#if _MSC_VER < 1900
// * nem biztos, hogy jó így *
#define THROW_BADALLOC
#define THROW_NOTHING
#else
// C++11 vagy újabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#else
#if __cplusplus < 201103L
// C++2003 vagy régebbi
#define THROW_BADALLOC throw (std::bad_alloc)
#define THROW_NOTHING throw ()
#else
// C++11 vagy újabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#endif
START_NAMESPACE
int allocated_blocks();
END_NAMESPACE
#if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE
int mem_check(void);
END_NAMESPACE
#endif
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
#include <cstdio>
START_NAMESPACE
class atexit_class {
private:
atexit_class() {
#if defined(CPORTA) && !defined(CPORTA_NOSETBUF)
setbuf(stdout, 0);
setbuf(stderr, 0);
#endif
}
public:
static atexit_class& get_atexit_obj() {
static atexit_class instance; // singleton példány
return instance;
}
int check() {
return mem_check();
}
~atexit_class() {
check();
}
};
/// A statikus referencia minden fordítási egységben keletkezik, de
/// mindegyik egyetlen példányra fog hivatkozni a singleton minta miatt
static atexit_class& atexit_obj = atexit_class::get_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 gyűjtjük a nemtrace-vel összeakadó headereket, hogy előbb legyenek */
#include <fstream> // VS 2013 headerjében van deleted definició
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <functional>
#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, FILE* fp);
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;
/* Visual C++ 2012 miatt kell, mert háklis, hogy nincs megfelelő delete, bár senki sem használja */
void operator delete(void *p, int, const char *) THROW_NOTHING;
void operator delete[](void *p, int, const char *) THROW_NOTHING;
#define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
#ifdef CPORTA
#define system(...) // system(__VA_ARGS__)
#endif
#endif /*MEMTRACE_CPP*/
#endif /*FROM_MEMTRACE_CPP*/
#endif /*MEMCHECK*/
#endif /*MEMTRACE_H*/
/**
*
* \file string5_kesz.cpp
*
* Itt kell megvalósítania a hiányzó tagfüggvényeket.
* Segítségül megadtuk a C-ben megírt változatban (string1.c) használt függvényneveket.
*
* Ha valamit INLINE-ként valósít meg, akkor annak a .h-ba kell kerülnie,
* akár kívül akár osztályon belül definiálja. (Az inline függvényeknek minden
* fordítási egységben elérhetőknek kell lenniük)
* *
* A teszteléskor ne felejtse el beállítani a header állományban az ELKESZULT makrót.
* A VC saját memóriafogyás ellenőrzője csak debug módban (Debug->Start) működik!
*
*/
#ifdef _MSC_VER
// MSC ne adjon figyelmeztető üzenetet a stringkezelő függvényekre.
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream> // Kiíratáshoz
#include <cstring> // Stringműveletekhez
#include "memtrace.h" // a standard headerek után kell lennie
#include "string5.h"
using std::cin;
using std::ios_base;
/// Konstruktor: egy char karakterből (createStrFromChar)
String::String(char ch) {
// Meghatározzuk a hosszát
len = 1;
// Lefoglalunk a helyet a hossznak + a lezaró nullának
pData = new char[len+1];
// Betesszük a karaktert
pData[0] = ch;
pData[1] = '\0';
}
// Konstruktor: egy nullával lezárt char sorozatból (createStringFromCharStr)
String::String(const char *p) {
// Meghatározzuk a hosszát
len = strlen(p);
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, p);
}
// Másoló konstruktor
String::String(const String& s1) {
// Meghatározzuk a hosszát
len = s1.len;
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, s1.pData);
}
// operator=
String& String::operator=(const String& rhs_s) {
if (this != &rhs_s) {
delete[] pData;
len = rhs_s.len;
// Helyet foglalunk
pData = new char[len+1];
// Bemásoljuk a stringet, ami le van zárva 0-val így használható az strcpy is
strcpy(pData, rhs_s.pData);
}
return *this;
}
// [] operátorok: egy megadott indexű elem REFERENCIÁJÁVAL térnek vissza.
// indexhiba esetén dobjon egy const char * típusú hibát!
char& String::operator[](unsigned int idx) {
if (idx >= len) throw "String: indexelesi hiba";
return pData[idx];
}
const char& String::operator[](unsigned int idx) const {
if (idx >= len) throw "String: indexelesi hiba";
return pData[idx];
}
// + operátor, ami két stringet ad össze (concatString)
String String::operator+(const String& rhs_s) const {
String temp; // ide kerül az eredmény
// Meghatározza az új string hosszát
temp.len = len + rhs_s.len;
// Felszabadítja a temp adattaerületét
delete []temp.pData;
// lefoglalja a memóriát az új stringnek.
temp.pData = new char[temp.len+1];
// Az elejére bemásolja az első stringet
strcpy(temp.pData, pData);
// Bemásolja a második stringet.
strcat(temp.pData, rhs_s.pData);
return temp; // visszatér az eredménnyel
}
// << operator, ami kiír az ostream-re
std::ostream& operator<<(std::ostream& os, const String& s0) {
os << s0.c_str();
return os;
}
// << operátor, ami beolvas az istreamről egy szót
std::istream& operator>>(std::istream& is, String& s0) {
unsigned char ch;
s0 = String(""); // üres string, ehhez fűzünk hozzá
std::ios_base::fmtflags fl = is.flags(); // eltesszük a régi flag-eket
is.setf(ios_base::skipws); // az elején eldobjuk a ws-t
while (is >> ch) {
is.unsetf(ios_base::skipws); // utána pedig már nem
if (isspace(ch)) {
is.putback(ch); // na ezt nem kérjük
break;
} else {
s0 = s0 + ch; // végére fűzzük a karaktert
}
}
is.setf(fl); // visszaállítjuk a flag-eket
return is;
}
#ifndef STRING_H
#define STRING_H
/**
* \file string2_kesz.h
*
* Ez a fájl tartalmazza a
* - String osztály deklarációját
* - az inline függvényeket. Ha valamit inline-ként akar megvalósítani,
* akkor azt ebbe a fájlba írja! Tipikusan a rövid kódokat szokás
* inline-két megvalósítani (pl: c_str).
* Más függvényeket ill. definíciókat ne írjon a .h fájlba!
*
* A C-ben megírt (string1.c) függvények most tagfüggvényekké váltak, és
* eltűnt az első paraméterük (s0) (ebből lett a this).
* A nevük is megváltozott, mert most már az összetartozást, és a
* paraméterek típusára való utalást már nem a név hordozza, hanem az osztály.
* A createString... alakú függvényekből konstruktorok keletkeztek.
* A disposeString destruktorrá alakült át.
* Egyes műveletvégző függvényekből pedig operátor függvény lett.
*/
/**
* Az Ön feladata a string2.cpp fájlban megvalósítani (definiálni) az egyes
* függvényeket.
*
* Ahogyan halad a megvalósítással egyre több tesztesetet kell lefuttatni,
* ezért az ELKESZULT makró értéket folyamatosan növelje a feladatsorszámoknak
* megfelelően!
*
* Tanulságos a megvalósítás előtt már a megnövelt értékkel is lefordítani
* a programot, és elemezni a kapott hibajelzést.
*
*/
#define ELKESZULT 13
/**
* \section fel Feladat:
* A tantermi gyakorlatokon, valamint a 3. laborgyakorlaton is foglalkoztunk egy
* olyan sztring (String) adatszerkezet és a rajta műveleteket végző függvények
* megtervezésével/impelmentálásával ami dinamikusan tárol és annyi memóriát foglal
* amennyi a tároláshoz szükséges.
*
* Ezeket és a tanultakat felhasználva a string2.h és a string2.cpp állományokban
* definiáljon ill. implementáljon egy olyan sztring (String) osztályt C++ nyelven, ami
* dinamikusan tárol és rendelkezik az alábbi tulajosnágokkal!
*
* 1 A paraméter nélkül hívható konstruktora üres sztringet hozzon étre!
* 2. Van olyan tagfüggvénye ( c_str() ), ami C-sztringgel, azaz nullával lezárt
* karaktersorozatra mutató pointerel (const char *) tér vissza.
* 3. Van olyan konstruktora, ami karakterből hoz létre sztringet.
* 4. Van olyan konstruktora, ami C-sztringből (const char*) hoz létre sztringet.
* 5. Az osztályból létrehozott objektum legyen átadható értékkparaméterként!
* 6. Támogassa a többszörös értékadást (b = a = a)!
* 7 Legyenek olyan operárorai (operator+), amivel a sztring végéhez sztringet,
* és karaktert lehet fűzni!
* 8. Lehessen karakterhez is sztringet fűzni a + operátorral!
* 9. A tárolt a karakterek legyenek elérhetőek a szokásos módon indexeléssel!
* Az indexeléssel elér elem legyen használható balértékként is!
* A konstans objektumok is legyenek indexelhetők.
* Az indexelés operátor hiba esetén dobjon const char * kivételt!
* 10. Készítsen olyan << operátort, amivel egy sztring kiírható egy ostream típusú
* objektumra!
*
* Szorgalmi feladatok:
* 11. Készítsen olyan fűzhető >> operátort, amivel be tud olvasni egy szót egy sztring-be!
* A beolvasó működjön úgy, mint a scanf %s, azaz a szó végét white space határolja!
* A szó eleji white space karaktereket pedig el kell dobni.
* *Megj: az istream wshite space kezelése a flags() tagfüggvénnyel szabályozható
* 12. Próbálja ki az ékezetes karakterek rendezését is! Ehhez elkészítettünk egy
* egyszerű kódrészletet ami qsort() függvényt használ.
* Értse meg a rendez.cpp fájlban levő kód működését és futtassa a programot!
* 13. A setlocale függvényhívás beállítja a karakterek és sztringek összehasonlításához
* szükséges nyelvi környezetet (LC_COLLATE) próbálja ki! Változott a rendezési
* sorrend?
*/
#include <iostream>
/**
* Header fájlokból megfontoltan kell include-ot használni.
* Névteret azonban nem célszerű kinyitni, mert annak hatása zavaró lehet
* ott ahol ez a header include-olva lesz.
*/
#ifndef MEMTRACE
#error "definialja projekt szinten a MEMTARCE makrot!"
#endif // MEMTRACE
/**
* A String osztály.
* A 'pData'-ban vannak a karakterek (a lezáró nullával együtt), 'len' a hossza.
* A hosszba nem számít bele a lezáró nulla.
*/
class String {
char *pData; /// pointer az adatra
size_t len; /// hossz lezáró nulla nélkül
public:
/// Az első két feladatot előre megoldottuk, de lehet, hogy nem jól.
/// Az üres string reprezentációja nem szerencsés, mert így NULL pointerré
/// konvertál a c_str(), ami külön kezelést igényel a későbbiekben, így
/// a teszt program sem fogadja el.
/// Gondolja végig, és változtassa meg!
/// Két lehetőség van:
/// a) nem NULL pointert tárol, hanem téynlegesen üres sringet.
/// b) a c_str() üres stringet ad vissza
/// Bármelyik jó, mert ez az osztály belügye.
size_t size() const { return len; }
/// Default konstruktor:
String() :pData(0), len(0) {}
/// C-stringet ad vissza
const char* c_str() const { if (pData) return pData; else return "";}
/// Konstruktor: egy char karakterből (createStrFromChar)
String(char ch);
/// Konstruktor: egy nullával lezárt char sorozatból (createStringFromCharStr)
String(const char *p);
/// MÁSOLÓ konstruktor, ami a createStringFromString-ből keletkezett
/// @param s1 - String, amiből létrehozzuk az új String-et
String(const String& s1);
/// Destruktor (disposeString)
~String() { delete[] pData; }
/// Egyéb tagfüggvények:
/// Kiírunk egy Stringet (debug célokra) (ez kész)
/// Elötte kiírunk egy tetszőleges szöveget.
/// @param txt - nullával lezárt szövegre mutató pointer
void printDbg(const char *txt = "") const {
std::cout << txt << "[" << len << "], "
<< (pData ? pData : "(NULL)") << std::endl;
}
/// Operátorok:
/// Értékadó operátor is kell !
/// @param rhs_s - jobboldali String
/// @return baoldali (módosított) string (referenciája)
String& operator=(const String& rhs_s);
String& operator+=(const String& rhs_s) {
*this = *this + rhs_s;
return *this;
}
/// Két Stringet összefűz (concatString)
/// @param rhs_s - jobboldali String
/// @return új String, ami tartalmazza a két stringet egmás után
String operator+(const String& rhs_s) const ;
/// Sztrinhez karaktert összefűz (concatString)
/// @param rhs_c - jobboldali karakter
/// @return új String, ami tartalmazza a két sztringet egymás után
String operator+(char rhs_c) const { return *this + String(rhs_c);}
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett, de ezt bal oldalon is lehet használni
/// @param idx - charakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
char& operator[](unsigned int idx);
/// A string egy megadott indexű elemének REFERENCIÁJÁVAL tér vissza.
/// charAtString-ből keletkezett. Konstans stringre alkalmazható.
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
/// @param idx - karakter indexe
/// @return karakter (referencia)
/// Indexelési hiba esetén const char* kivételt dob (assert helyett).
const char& operator[](unsigned int idx) const;
void erase() { *this = ""; }
};
/// Globális függvények:
/// kiír az ostream-re (printString)
/// Nem célszerű using-ot használni, mert ez egy include file. Így ki kell írni az std::-t
/// @param os - ostream típusú objektum
/// @param s0 - String, amit kiírunk
/// @return os
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen, mert a c_str() segít
std::ostream& operator<<(std::ostream& os, const String& s0);
/// Beolvas az istream-ről egy szót egy string-be.
/// @param is - istream típusú objektum
/// @param s0 - String, amibe beolvas
/// @return is
/// Vigyázat nem tagfüggvény! Nem is tűnik el az s0 !
/// Nem kell, hogy barát legyen mert van Str + ch
std::istream& operator>>(std::istream& is, String& s0);
/// String operator+(char ch, const String& str);
/// Vagy inline, vagy nem itt a helye!
/// Nem kell, hogy barát legyen mert tudunk chr-ből str-be konvertálni
/// két str pedig összeadható
inline String operator+(char ch, const String& str) { return String(ch) + str; }
#endif
#ifndef CALLBACK_H
#define CALLBACK_H
/// Callback objektum.
/// Nem ismeri modellt se, s a felhasznli felletet se.
class GombCallback { // callback funkcihoz
public:
virtual void callBack() = 0;// virtulis cb. fggvny
};
#endif
\ No newline at end of file
/**
* \file felhfelulet.h
*
* A felhasznli felletet megvalst osztlyok definicii
* Nem ismeri a modellt.
*
*/
#ifndef FELULET_H
#define FELULET_H
#include "callback.h"
/// Gomb.
/// A gomb "megnyomsra" meghvdik a nnyom() tagfggvny
class Gomb {
GombCallback &cb; // callback objektum referencia
public:
Gomb (GombCallback &t) :cb(t) {}// referencia inic.
/// A felhasznl felleten megnyomtk a gombot
void nyom() { // megnyomtk
cb.callBack();
}
};
#endif // FELULET_H
/**
* Felhasznli fellet s a modell kapcsolata
* Callback fv. dem
*
*/
#include <iostream>
#include "modell.h"
#include "felhfelulet.h"
using std::cout;
using std::endl;
using std::cin;
int main() {
Kapcsolo k1;
Gomb g1(k1); // itt ktjk ssze a felhasznli felletet s a modellt.
cout << "Megyomjuk a gombot: " << endl;
cin.ignore(100, '\n');
g1.nyom(); // felleten megnyomtk
cout << "Megint megyomjuk a gombot: " << endl;
cin.ignore(100, '\n');
g1.nyom(); // jra
cout << "Ismet megyomjuk a gombot: " << endl;
cin.ignore(100, '\n');
g1.nyom(); // jra
return 0;
}
/**
* \file modell.cpp
*
* A modell-t megvalst osztlyok deklarcii
* Nem ismeri a felhasznli felletet.
*
*/
#include <iostream>
#include "modell.h"
using std::cout;
using std::endl;
/// Kikapcsol
void Kapcsolo::ki() {
bent = false;
cout << " Kikapcs" << endl;
}
/// Bekapcsol
void Kapcsolo::be() {
bent = true;
cout << " Bekapcs" << endl;
}
/// GombCallback callBack fggvnynek megvalstsa
/// A felhasznli fellet ezt hvja
void Kapcsolo::callBack() {
if (bent)
ki();
else
be();
}
/**
* \file modell.h
*
* A modell-t megvalst osztlyok defincii
* Nem ismeri a felhasznli felletet.
*
*/
#ifndef MODELL_H
#define MODELL_H
#include "callback.h"
/// Drot
/// A drot modelljt megvalst osztly
class Drot {
public:
/// Valahogy mkodik.
/// A plda szempontjbl rdektelen
void set() {}
};
/// Kapcsol
/// A kapcsolt modelljt megvalst osztly
class Kapcsolo :public Drot, public GombCallback {
bool bent; // llapot
public:
Kapcsolo() :bent(false) {}
/// Kikapcsol
void ki();
/// Bekapcsol
void be();
/// GombCallback callBack fggvnye
/// A felhasznli fellet ezt hvja
void callBack();
};
#endif // MODELL_H
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="nyomogomb" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/nyomogomb" 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/nyomogomb" 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="-Wall" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="callback.h" />
<Unit filename="felhfelulet.h" />
<Unit filename="gomb_demo.cpp" />
<Unit filename="modell.cpp" />
<Unit filename="modell.h" />
<Extensions>
<code_completion />
<envvars />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
<?xml version="1.0" encoding="windows-1250"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="nyomogomb"
ProjectGUID="{31D38A47-C055-4EE7-9DBA-FB41EFC57F02}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/nyomogomb.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/nyomogomb.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/nyomogomb.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\gomb_demo.cpp">
</File>
<File
RelativePath=".\modell.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\callback.h">
</File>
<File
RelativePath=".\felhfelulet.h">
</File>
<File
RelativePath=".\modell.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
/*
* \file polimorf.cpp
*
* Tbbszrs rkls s a polimorf viselkeds,
* valamint a dynamic_cast memutatsa.
*
* A dynamic_cast-hoz fontos, hogy a fordtskor legyen
* engedlyezve a Run-Time Type Info (RTTI) generlsa
* (Vis.stud: /GR opci)
* GCC-nl automatikus
*
*/
#include <iostream>
#include <stdexcept>
using namespace std;
/// A oszty.
/// (struct: mindene publikus)
struct A {
void f() { cout << " A::f()\n"; }
void f(int) { cout << " A::f(int)\n"; }
virtual ~A() {} // csak ezrt virt., hogy legyen RTTI inf
};
/// B oszty.
/// (struct: mindene publikus)
struct B {
void f(double) { cout << " B::f(double)\n"; };
};
/// C oszty.
/// (struct: mindene publikus)
struct C {
void f(int*) { cout << " C::f(int*)\n"; };
};
/// AB oszty.
class AB :public A, public B {
public:
// Tbbszrs rklsnl az azonos nev tagfggvnyekrl a fordt felttelezi,
// hogy teljesen eltr viselkedst valstanak meg, ezrt egyik elrst sem
// engedi automatikusan, hiba publikus az rkls.
using A::f; // gy elrhetk az A-beli f()-ek
using B::f; // gy elrhet a B-beli f()is
void f() {
cout << " AB::f()\n";
A::f();
f(1); // A::f(int)
f(1.2); // B::f(double)
}
};
/// Kiprobljuk...
int main() {
AB ab;
cout << "Fuggvenyek [ab.A::f(), ab.f(int) ab.f(doube) ab.f()]" << endl;
ab.A::f();
ab.f(5); // A::f(int)
ab.f(6.3); // B::f(double)
ab.f(); // AB::f()
A *Ap = &ab; // az upcast automaiikus
B *Bp = &ab; // az upcast automaiikus
cout << endl << "Pointerek konvertalasa:" << endl;
AB *ABp = dynamic_cast<AB*>(Ap); // biztonsgos down cast
if (ABp != 0) {
cout << "Sikeres volt a down cast" << endl;
ABp->f();
} else {
cout << "A down cast nem sikerult" << endl;
}
C *Cp = dynamic_cast<C*>(Ap); // ez nem fog menni
if (Cp == 0) cout << "AB* nem konvertalhato C*-ra" << endl;
cout << endl << "Referencia konvertalasa:" << endl;
// Referencia konvertlsnl a hibajelzs kivetellel jn
try {
AB& ab2 = dynamic_cast<AB&>(*Ap);
cout << "Sikeres volt a down cast referenciara is:" << endl;
ab2.f();
cout << "Kiserlet C referenciara valo konvertziora:" << endl;
C& c2 = dynamic_cast<C&>(*Ap);
} catch (exception& e) {
cout << e.what() << endl;
}
return 0;
}
<?xml version="1.0" encoding="windows-1250"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="polimorf"
ProjectGUID="{F21BFD5C-66B3-48F9-B7E7-04B1D6C254D0}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/polimorf.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/polimorf.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/polimorf.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\polimorf.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
#include <iostream>
//#define ROSSZ
using std::cout;
using std::endl;
struct Data {
Data() { std::cout << "Data()\n"; }
~Data() { std::cout << "~Data()\n"; }
};
struct A {
A() { std::cout << "A()\n"; }
virtual void f() { std:: cout << "A::f()\n"; }
#ifdef ROSSZ
~A() { std::cout << "~A()\n"; f(); }
#else
virtual ~A() { std::cout << "~A()\n"; f(); }
#endif
};
struct B : A {
Data d[5];
B() { std::cout << "B()\n"; }
void f() { std:: cout << "B::f()\n"; }
~B() { std::cout << "~B()\n"; }
};
int main() {
B b;
// delete ap;
return 0;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="virt_destruktor" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/virt_destruktor" 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/virt_destruktor" 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="-Wall" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="main.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
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