[MEGOLDVA] class és statikus változók

 ( Kuvik | 2009. július 17., péntek - 0:50 )

Újabb problémába ütköztem.

Van egy függvényem, aminek van egy statikus változója, értelemszerűen azért, hogy a hívások között is megőrizze az értékét. Ezt a függvényt több különböző helyen (különböző argumentumokkal) is meg szeretném hívni. Alapesetben ilyenkor a statikus változó minden hívásnál felülíródik, tehát nem tudom hasznát venni, mert nem különülnek el az egyes hívások attól függően, hogy honnan hívom (nem hívódik kvázi több példányban).

Ezt próbálom egy osztállyal kiküszöbölni.

Eddigi sikertelen kísérleteim:

- az osztálynak egy tagfüggvénye van (ez az előbb említett függvény), itt úgy gondoltam, hogy, ha az adott típusból létrehozok példányokat, akkor ez a tagfüggvény is több példányban fog létezni

- ami a függvényben statikus változó volt, azt az osztály (private) adattagjává tettem, a függvény továbbra is tagfüggvény, csak nincs benne statikus változó, hanem az adattagba "menti" a szükséges értékeket

- próbáltam az egyes példányokat és az adattagot is statikusként deklarálni

------------------------------------
TÜNETEK, azonosak mindegyik esetben:

- a megőrizni kívánt értékek mindegyik esetben "keresztbeíródnak", még akkor is, ha privát adattagként vannak kezelve (mintha az adattag csak egy példányban létezne)

- ha semmilyen static deklaráció nincs, az egyes példányok akkor sem szűnnek meg (valószínűleg), amikor kikerül a végrehajtás abból az egységből (egy függvény), amiben létre lettek hozva, mivel az eltárolni kívánt értékek (legalábbis a "keresztbeíródott" hülyeségek) úgy néz ki, hogy megmaradnak. Igaz ugyan hogy nem írtam külön konstruktort/destruktort, de úgy tudom, hogy ilyen esetben ettől függetlenül is meg kellene szűnnie a példányoknak.

Mi lehet a hiba?

-------------------------------------

MEGOLDÁS:

hiba: PEBKAC minősített esete

A jó megoldás részletei végig megvoltak, csak az egyes hibák javítása közben mindig újabbakat csináltam. Az egész felfordulás (kissé leegyszerűsítve) arra vezethető vissza, hogy egy tagfüggvény egy feltétel szerint módosította a statikus változót, ill. az azt helyettesítő privát adattagot, amit én az osztály/konstruktor számlájára írtam...

A jó megoldás végül:

- kell tisztességes konstruktor
- az osztály _pédányait_ static-ként kell létrehozni (ahogy a Stroustrup 10.4.8-ban szépen le is van írva)

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

A static egy fuggveny lokalis valtozojara vonatkozoan azt csinalja, amit irtal: megorzi az erteket hivasok kozt, gyakorlatilag egy, csak az adott fv-bol elerheto globalis valtozo lesz belole. Ennek megfeleloen nem is a stack-en jon letre, mint a lokalis valtozok altalaban.

A static egy osztaly adattagjara is hasonloan hat: osszesen 1 peldany jon letre belole, amit az osszes objektum kozosen hasznal (viszont private esetben csak osztalyon belulrol erheto el, mondjuk a globalis valtozoktol elteroen).

Neked az kell, hogy tobb tagvaltozod is legyen (vagy legalabbis tobb olyan valamid, amiben erteket tarolhatsz). A static pont ezt akadalyozza meg.

Azt viszont nem ertem, hogy mi az, hogy tobb kulonbozo helyrol meghivva mast es mast lasson? Letrehozhatsz egyszeruen tobb objektumpeldanyt az adott osztalybol, igy ezeknek kulon-kulon adatmezoi lesznek. Szoval jo uton jarsz, de ird le egy picit pontosabban (akar pszeudokoddal), hogy mit akarsz.

--
"Digital content is not a tangible good and should not be subject to the same liability rules as toasters." - Francisco Mingorance, BSA

Teljesen egyetértek azzal, hogy legyen több osztály, több adattaggal.
A teljesség kedvéért egy másik (sok szempontból hátrányos) megoldás: http://hup.pastebin.com/m239d6079
A template paraméter mondja meg, hogy "melyik" függvényt hívod meg (és nyilván a függvényben nem kötelező a value használata).
Az ilyen megoldások használata persze erősen ellenjavallt.

"...legyen több osztály..."

Több _példány_ az adott osztályból, nem?

De, persze. Figyelmetlen vagyok.

"Letrehozhatsz egyszeruen tobb objektumpeldanyt az adott osztalybol, igy ezeknek kulon-kulon adatmezoi lesznek."

Na,hát ez az, én is így gondoltam, ld. az első és második próbálkozásomat, de valamiért mégsem így viselkedik, hanem úgy, mint abban az esetben, amit a statichoz írtál.

egyébként ilyesmiről van szó:

class osztály{
   private:
   public:
      típus függvény(...){
         ...
         static típus változó;
         ...
         változó=érték;
         ...
      };
};

a felhasználás helyén:

osztály példány1;
osztály példány2;

típus eredmény1=példány1.függvény(...);
típus eredmény2=példány2.függvény(...);

- ugyanezt próbáltam úgy is, hogy nem a függvényen belül van egy static változó, hanem az osztály private adattagja tárolná a szükséges értékeket két hívás között

- ez a felállás felvet még néhány kérdést, ha a "felhasználás helye" pl. egy függvény és pl. periodikusan hívódik, akkor nem biztos, hogy jó ötlet minden híváskor újradeklarálni a példányokat (mi lesz ilyenkor a static változókkal, vagy az adattagokkal?), ill., ha a végrehajtás elhagyta a felhasználás helyét, akkor megszűnnek-e a példányok? (Nekem most valamiért úgy tűnik, hogy nem, pedig szerintem meg kellene szűnniük. Miért nem?)

Itt is benne van a static. Szoval 1 valtozod lesz.
Amit irtal, az nagyjabol megegyezik ezzel:

típus változó;

class osztály{
   private:
   public:
      típus függvény(...){
         ...
         változó=érték;
         ...
      };
};

Azzal a kulonbseggel persze, hogy a ezt elered mashonnan is, nem csak a fuggvenyen belulrol. De igy remelem latod miert nem azt csinalja, amit szeretnel.

Igy miert nem jo?

class osztály{
   private:
   típus változó;
   public:
      típus függvény(...){
         ...
         változó=érték;
         ...
      };
};

a felhasználás helyén:

osztály példány1;
osztály példány2;

típus eredmény1=példány1.függvény(...);
típus eredmény2=példány2.függvény(...);

--
"Digital content is not a tangible good and should not be subject to the same liability rules as toasters." - Francisco Mingorance, BSA

Ezt már próbáltam (nem olvastad végig az előző hozzászólásomat):

"- ugyanezt próbáltam úgy is, hogy nem a függvényen belül van egy static változó, hanem az osztály private adattagja tárolná a szükséges értékeket két hívás között"

valamiért ugyanúgy viselkedik mint a staticos eset, erre szeretnék rájönni, hogy miért.

Ha ez valóban így van működés szempontból, akkor szerintem a legjobb, ha mutatsz némi kódot, hátha úgy látjuk, hogy miért lehet az, ami.

Most nincs kéznél, de gyakorlatilag (egyelőre) majdnem ugyanaz, csak más változónevekkel, mint amit korábban írtam. Ami nem látszik, hogy az egész egy dll-be fordul, arra gondoltam, hogy esetleg ez befolyásolhatja a változók elérhetőségét, bár ez nem tűnik valami logikus magyarázatnak.

Vegigolvastam. Azt hittem, hogy a private-on belul is staticot probaltal, igy ertelmeztem az "ugyanezt probaltam"-ot.

--
"Digital content is not a tangible good and should not be subject to the same liability rules as toasters." - Francisco Mingorance, BSA

Ja, egyébként kínomban már úgy is próbáltam... :)

hali!

azon filóztam hogy ha a különböző hívási helyeken rendelkezésre tud állni különböző példány a class-ból ami tartalmazná az ominózis statikus változót, akkor mér nem felejted el a statikus változót, hanem tárolod annak különböző értékeit a hívások helyén (ha a class-t tudod gondolom ez se lehet probléma) és adod át mutatóként a függvénynek?

Ha jól értem, amit mondasz, akkor pont ezt szeretném elkerülni. A függvényt sok helyről hívnám, és így ugyanannyiszor be kellene tenni a kódba a megőrizni kívánt értékek kezelését.

Amit írsz, az funkcionálisan egyenértékű lenne a class-os megoldással (és még van pár lehetőség), de én nem erre törekszem, hanem a kódot szeretném kissebbé, átláthatóbbá tenni, ehhez pedig pont az kellene, hogy ezzel a bizonyos változóval ne kelljen a függvényen, vagy legalábbis az osztályon kívül foglalkozni.

ezekszerint férreértettelek, ebben az esetben a megkülönböztetendő meghívások között van valami egyértelmű különbség? mint pl mindíg más a paraméterek száma, vagy egy változó értéke egyértelmüsíti hogy "milyen" meghívásról van szó? mer ha egy értékre vissza lehetne vezetni, akkor egy statikus map-ba rakhatnád a különböző meghívásokhoz tartozó változókat és ez alapján az egyéni jellemző szerint választhatnád ki ami kell!

ezekszerint férreértettelek, ebben az esetben a megkülönböztetendő meghívások között van valami egyértelmű különbség? mint pl mindíg más a paraméterek száma, vagy egy változó értéke egyértelmüsíti hogy "milyen" meghívásról van szó? mer ha egy értékre vissza lehetne vezetni, akkor egy statikus map-ba rakhatnád a különböző meghívásokhoz tartozó változókat és ez alapján az egyéni jellemző szerint választhatnád ki ami kell!

-edit-
bocsi megremegett az ujjam a beküld gombon :S

Sajnos nem lehet az értékek alapján elkülöníteni a hívásokat. Amúgy ez nem tűnik valami elegáns megoldásnak, sőt robusztusnak sem, csak akkor, ha az értékek _tényleg_ nagyon elkülöníthetők, vagy kizárják egymást.

bocsi, de még mindíg nem írtál konkrét példát, így csak lövöldözünk a levegőbe egy olyan probléma körül aminek csak a felszínét ismerjük...

és igazából a konkrét problémára nem igazán van szebb megoldás, ha ismernénk az okokat a megvalósítás részleteit, abban már lehetne elegáns megoldást keresni!

de az hogy egy statikus változó legyen statikus de valami mágikus módon elkülönítve 3* :D so érted..

"de az hogy egy statikus változó legyen statikus de valami mágikus módon elkülönítve 3* :D"

Pontosan ezt szeretném, de nem kell hozzá mágia, ezt a "hatást" osztállyal meg lehet valósítani, ez nem is probléma. A probléma az, hogy valamiért a class-os implementáció mégsem így viselkedik, holott minden emberi számítás szerint így kellene neki (ld. fentebbi hozzászólások).

Egyébként nem ragaszkodok a static változóhoz, annak csak a kérdéses fügvény eredeti formájában volt értelme, így, hogy több helyen akarom használni, már nincs, vagy legalábbis nem abban a formában, ahogy eredetileg a függvényben volt.

értemén, csak ha jól értettem létrehozol arra egy külön class-t hogy ezt példányosítsd különböző helyeken, hogy különböző legyen az egyetlen függvényének static változója, igaz?

és erre gondoltam én hogy kicsit túlbonyolítás, és akkor már azt az egy nyomorult változót is őrizgethetnéd a class helyett... ami semmivel nem elegánsabb, vagy kevésbé elegáns, csak kevésbé bonyolult, és kisebb a hibalehetőség!

ha félreértettelek, és a class egy nagyobb egység, ami teszemazt három példányban létezik és teszi a dolgát, és ennek egy tagfüggvényének statikus változójáról beszélünk akkor a kiragadott példák miatt teljesen félreértettelek :S

"értemén, csak ha jól értettem létrehozol arra egy külön class-t hogy ezt példányosítsd különböző helyeken, hogy különböző legyen az egyetlen függvényének static változója, igaz?"

Pontosan. De ilyenkor elvileg már nem kell, hogy a kérdéses változó ténylegesen static legyen (sőt...), ha az osztály adattagja. Ezzel vannak gondok, hogy valamiért mégsem úgy viselkedik, ahogy az osztálytól várnám.

"...a class egy nagyobb egység, ami teszemazt három példányban létezik és teszi a dolgát, és ennek egy tagfüggvényének statikus változójáról beszélünk..."

Igen, erről volna szó, csak azzal kapcsolatban vannak még nyitott kérdések, hogy a tagfüggvénynek lehet-e ilyenkor static-ként deklarlát változója (létrejön-e több példányban?), vagy esetleg ezt helyettesítsem az osztály egy adattagjával, ill., hogy az utóbbi megoldás miért nem úgy viselkedik, ahogy várjuk.

joh, akkor kezdjük az elején!

a static-ként megadott változó a függvényen belül mindíg a fügvényre nézve lessz static nem a példányra, és nem is az osztályra! tehát ez neked nem jó megoldás...

de ha az osztály adattagjaként szerepel akkor annak egyértelmű, hogy példányonként külön értéke kell hogy legyen, különben értelmetlen lenne példányosítani az objektumokat!

tehát triviális hogy a következő kis kódnak:
class testclass {
private:
int variable;
public:
void func(int nevvar) {
std::cout << "Before: " << variable << std::endl;
variable = nevvar;
std::cout << "After: " << variable << std::endl;
}
};

int main()
{
testclass inst1;
testclass inst2;

inst1.func(5);
inst2.func(10);
inst1.func(15);
inst2.func(20);

return 0;
}

A kimenete így kell kinézzen:
Before: *valami
After: 5
Before: *valami
After: 10
Before: 5
After: 15
Before: 10
After: 20

szóval ha a te kódodban nem ezt produkálja akkor az idevonatkozó részeket kimásolhatnád ide, mer innentől kezdve nem logikai hanem elírási problémánk van valszín!

Igen, pontosan erről van szó, és ahogy írtad, az a probléma, hogy nem ezt produkálja.
Most nincs kéznél a kód, később majd megpróbálok felrakni részleteket.

Mindenkepp rakj fel kodokat az osztaly implementaciojabol is, meg az osztalyt hasznalo fuggvenyekbol is. Probalj meg egyszeru teszteseteket osszerakni, hogy lassuk, pontosan mit is csinalsz. Ez a sokponttal tarkitott megoldas azert nem jo, mert a fene se tudja, hogy a sok pont mogott milyen magikus dolgot csinalsz, ami esetleg befolyasolhatja a mukodest.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

"- ha semmilyen static deklaráció nincs, az egyes példányok akkor sem szűnnek meg (valószínűleg), amikor kikerül a végrehajtás abból az egységből (egy függvény), amiben létre lettek hozva, mivel az eltárolni kívánt értékek (legalábbis a "keresztbeíródott" hülyeségek) úgy néz ki, hogy megmaradnak. Igaz ugyan hogy nem írtam külön konstruktort/destruktort, de úgy tudom, hogy ilyen esetben ettől függetlenül is meg kellene szűnnie a példányoknak."

Az álmoskönyv szerint nem jó ómen, ha nem inicializálod az osztályok adattagjait egy konstruktorral...

Gyanítom, hogy valami ilyesmit csinálsz:

class T
{
public:
	int t()
	{
		return i;
	}
	void setT(int t)
	{
		i=t;
	}
private:
	int i;
};

void test()
{
	T t;
	std::cout << t.t() << std::endl;
	t.setT(3);
}

int main()
{
	test();
	test();
}

A eredmény:
Az első test()-nél kiír némi szemetet, majd a következő hívásnál kiírja az előző hívásban beállított értéket. Azaz "az egyes példányok akkor sem szűnnek meg (valószínűleg), amikor kikerül a végrehajtás abból az egységből, az eltárolni kívánt értékek úgy néz ki, hogy megmaradnak."

Miért?
Mert nem inicializáltad a privát változót, a default konstruktor pedig az int default konstruktorát azaz a nagy semmit futtatja. Tehát az i értéke az, amit a memóriában ott talált. A fordító által generált destruktor szintén a semmi.
Következő hívásnál ugyanez történik, viszont az osztályod a stack-en ugyanott jön létre mint az előző, azaz az i címe az lesz mint az előző i-jé, emiatt tartalma is.

Tehát:
Írj konstruktort.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Igen, gondoltam már rá, hogy ekörül (is) lehet a probléma (ld. korábbi hsz.-ok), de még nem volt időm kipróbálni, először meg azt gondoltam, hogy default is működni fog.

Amúgy meg kezdem érteni az aláírásodat :)

Ez az első lépés. :)

Egyébként a C++-ban sincs sok mágia, ha rájössz a saját logikájára, akkor kevés meglepetés ér. Csak ehhez jó könyvek és sok olvasás kell...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Es/vagy nemi intuicio. Minel kevesebb konyvvel rendelkezel annal tobb intuicio.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Nyert. Az általam írt konstruktor megszünteti a "keresztbeírás" problémáját, de a feladatot még mindig nem sikerült teljesen megoldanom.

Az kellene még, hogy az egyes példányok azután is megmaradjanak, miután a végrehajtás kikerült abból a függvényből, ahol a példányt létrehoztam, ill. ugyanezek a példányok a függvény következő hívásánál is elérhetők legyenek.

Most nincs nálam a könyv, de ha jól emlékszem, Stroustrup azt írja a "A C++ programozási nyelv"-ben, hogy erre a célra az egyes példányokat ugyanúgy létre lehet hozni static-ként, mint ahogy ezt egy közönséges változóval tesszük deklaráláskor, tehát:

static típus példány

ahol a típus egy osztályt jelöl.

Erre azt írja, hogy a példányok maguktól csak a programfutás végén szűnnek meg. Ennek ellenére nekem ez nem működik.
Nem tudom, hogy probléma lehet-e, de ez az egész egy dll-ben van, nem tudom, hogy ilyenkor mi számít a végrehajtás végének, tehát, pl. amikor a dll-ben lévő függvény végrehajtódik, akkor azt nem tekinti-e a végrehajtás végének, és nem szünteti-e meg a példányokat.

A getinstance fuggveny statikus kell legyen, es a peldanyt tarolo privat tagnak is statiknak kell lenni. Ettol lesz perzisztens az egesz. Pont arrol szol a singleton cucc, hogy ezt a funkcionalitast nyujtja.

Pelda: http://codepad.org/sBDBOV3C

--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Köszönöm, ez jónak tűnik. Ki is próbáltam, de még nem működik teljesen, arra nem jöttem még rá, hogy hogyan tudok több példányt létrehozni. Most, ha megpróbálom, úgy tűnik, hogy nem jön létre új példány, hanem a getInstance() az először létrehozottra mutató pointert ad vissza (ez végülis azthiszem logikus, a singleton felépítés miatt).

Ezt kellene úgy módosítanom, hogy több példányt kezeljek vele (az már talán nem lesz(?) igazán singleton, de ez most mindegy)

Úgy gondolom, hogy a *getInstance() függvényt kellene ehhez módosítanom, de még nem értem teljesen, hogy hogyan működik. Azt látom, hogy visszaadja a létrehozott példányra mutató pointert, de csak feltételesen hozza létre az új példányt, ha az még nem létezik. Viszont úgy tűnik, hogy az itt szereplő pointer (m_instance), mivel static, ezért csak egy példány létezik belőle, ezért, ha a class egy újabb példányát akarom ezzel a kóddal létrehozni, akkor az előzőleg létrehozott példányra mutató pointert fogja visszaadni az "új" példánynak is. Vagyis ott vagyok, ahol voltam, van egy példányom, két különböző néven.

Ha a feltételt kiveszem a *getInstance()-ból, az meg (úgy gondolom) azért nem jó, mert akkor meg minden hívásnál csinál egy-egy új példányt.

Tehát nekem az kellene, hogy valahogy több példányt tudjak létrehozni, de miután létrehoztam őket, már ne akarjanak újra létrejönni. Kvázi, mint a példában, csak több példányra.

Kézenfekvő workaroundnak tűnik, ha a példányok létrehozása után meghívok egy init függvényt, ami átbillent egy globális statikus változót, amit aztán lehet feltételnek használni, de ez nem tűnik valami elegánsnak. Valahogy az osztályon belül kellene inkább megoldani, de erre még nem jutott eszembe semmi.

Csak al-pszeudokodban, mert ezt mar nem vagyok hajlando leprogramozni:

public:
static SingleTon *newInstance() {
    instpool << new SingleTon();
}
static SingleTon *getInstance(const int i) {
    return instpool[i];
}
static SingleTon *getLatestInstance(const int i) {
    return instpool[instpool.size()];
}
private:
    static set<SingleTon *> instpool;

Esetleg megoldhatod stackesen is, vagy, ha az osztalynak van valami keresheto tulajdonsaga (peldaul tudom, hogy az i erteke 85), akkor az alapjan is lehet keresoalgoritmust irni.
Ezzel melyen belementunk a poolozas birodalmaba, es nem is biztos, hogy ez a legjobb megoldas neked, csak azert irtam le, hogy ilyent is lass.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Azthiszem megvan :) Közben már én is gondolkodtam ilyesmin, hogy a pointerekből egy vektort kellene csinálni, de még nemigazán jöttem rá, hogy hogyan, úgyhogy ezt külön köszönöm :)

Innentől már azthiszem meg tudom oldani, mert az egyes pléldányok egy private adattagban tárolhatják, hogy melyik pointer vonatkozik rájuk.

Juj, de perverz. Viszont attol meg nem vagy beljebb, hogy az adott peldany tudja a sajat id-jat. Neked hivaskor is tudod kell ugyanezt. Erre figyelj oda.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Tényleg perverz :) Emiatt, mielőtt végleg ezt a megoldást választanám, visszatérnék egy kicsit arra a lehetőségre, amit a Stroustrup-könyvben olvastam (most itt van előttem a könyv):

"10.4.8. Lokális statikus adatok

A lokális statikus objektumok (7.1.2) konstruktora akkor hajtódik végre, amikor a végrehajtási szál először halad keresztül az objektum meghatározásán:

void f(int i)
{
   static Table tbl;
   ...
}

int main()
{
   f(0);
   ...
}

Itt tbl konstruktora f() első meghívásakor hívódik meg. Mivel tbl-t statikusként adtuk meg, így nem semmisül meg, amikor f()-ből visszatér a vezérlés és nem jön újra létre f() második meghívásakor."

Na, nekem pontosan ez kellene, ennek ellenére valamiért nekem mindig újra és újra végrehajtódik a konstruktor. Feltételezem, hogy én vagyok a hülye és nem Stroustrup, de vajon nekem ez miért nem működik?

Minek a konstruktora hajtodik vegre ujra es ujra? A statikus objektume? Az nem normalis dolog. Ha viszont egy objektum tartalmaz egy statikus adattagot (ekkor valojaban ez egy osztalyszintu adattag), akkor az osztalynak termeszetesen ettol fuggetlenul lehet tobb peldanya, ami termeszetesen tobb konstruktorlefutassal is jar.

Természetesen a statikus objektumé (ami nem tartalmaz statikus adattagot), és szerintem sem normális dolog, de nem értem, hogy hol a hiba.

tárgytalan, ld. fent :)

Ha a singleton menten haladsz, akkor ott nincs konstruktorhivogatas, hanem peldanykivetel van egy meghatarozott pool-bol. Most igy alomittas fejjel olyan is eszembe jutott, hogy gcc eseten mintha lenne valami __FUNCNAME__ makro, ami forditasi idoben kerul kifejtesre automatan. Ha e menten indexeled a peldanyaidat, akor jo lesz neked (persze ekkor nem set kell hanem map<char *, SingleTon *> Masik verzio egy if-elseif szerkezettel pool id-ket rendelni a fuggvenynevekhez. Igy ugyan egy uj usert be kell regisztralni a getInstance() fuggvenybe, de ennel rosszabb ugyse lehet mar.

Amugy nem ertem, a user fuggvenyek nem tudnak konkret id-t kapni sehogyse? Mert akkor csak a pool-lal kellene torodnod a SingleTon kodjaban, es minden fuggveny jo elore tudna a sajat id-jet.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

1. Írd le rendesen, hogy mit szeretnél, mert már 3x elolvastam és nem értem.

2. Mi a franc az, hogy "keresztbeíródnak"?

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

itt pontosan az van leírva, amit szeretnék: http://hup.hu/node/73603#comment-811189

a "keresztbeíródás" alatt pedig azt értem, hogy az osztály valamiért úgy viselkedik, mintha a privát adattag egy globális, statikus, egy példányban létező változó lenne, mintha az osztály példányai nem rendelkeznének saját példánnyal ebből a változóból, ezért minden függvényhíváskor ezt az egy változót írnák felül. Ezt szeretném kideríteni, hogy miért van.

Végigolvastam az összes hozzászólást.

1, Ha jól látom, már "elérhető" számodra a kód, tehát ha megtisztelnél vele minket, az sokat segítene. Neked. És nekünk.

2, Ha jól értem, ez a probléma :
"Ezt a függvényt több különböző helyen (különböző argumentumokkal) is meg szeretném hívni. Alapesetben ilyenkor a statikus változó minden hívásnál felülíródik, tehát nem tudom hasznát venni, mert nem különülnek el az egyes hívások attól függően, hogy honnan hívom (nem hívódik kvázi több példányban)."

2,a : Mi az "alapeset" ?
2,b : Hogyan akarod, hogy a különböző hívások elkülönüljenek ? ( Polimorfizmus ? )
2,c : Mit jelent az, hogy egy függvény több példányban hívódik ? Nem hallottam még ezt.

3, Volt még ilyen is : "Az kellene még, hogy az egyes példányok azután is megmaradjanak, miután a végrehajtás kikerült abból a függvényből, ahol a példányt létrehoztam, ill. ugyanezek a példányok a függvény következő hívásánál is elérhetők legyenek."

Namost ha jól értem, egy függvényben példányosítasz egy osztályt ( létrehozol egy objektumot ), és azt várod el, hogy a függvény befejeztével, majd egy újabb hívással elérhető legyen az imént létrehozott objektum.

3,a : Függvényen belüli statikus változók ( nem a static-ra gondolok, hanem a stack-ben létrejövő bitsorozatokra ) bizony függvény befejeztével törlődnek.
3,b : Vagy dinamikusan hozod létre, vagy megadod egy változó címét a függvénynek, vagy globális változót használsz, vagy a függvényben static pointer-t állítasz be egy külső változó címére, stb.

4, Mielőtt DLL-be raksz valamit, érdemes lenne külön letesztelni. Ha jól értem, most van egy működésképtelen valamid, amit DLL-ből hívogatsz.

Ha nem ragaszkodsz az osztalyokhoz, akkor talan igy is megoldhatod:

int fofuggveny(int &staticvaltozo, int arg1, int arg2)
{
  ++staticvaltozo;
  return arg1+arg2;
}

int kisfgv1(int arg1, int arg2)
{
  static int ertek1 = 0;
  int retval = fofuggveny(ertek1, arg1, arg2);
  x = ertek1;
  return retval;
}

int kisfgv2(int &x, int arg1, int arg2)
{
  static int ertek2 = 0;
  int retval = fofuggveny(ertek2, arg1, arg2);
  x = ertek2;
  return retval;
}

int main(int argc, char *argv[])
{
  int stvaltozo;
  kisfgv1(stvaltozo, 1, 2);
  kisfgv1(stvaltozo, 2, 3);
  kisfgv2(stvaltozo, 3, 4);
  return 0;
}

Ennek a lenyege, hogy megmarad az egy fuggvenyed, amit mindig hivogattal eddig, ez a fofuggveny(), csak ki lett egeszitve egy parameterrel: egy valtozora mutato referencia, amit ugy hasznal mint az eddigi statikus valtozo. Emellett pedig megjelennek a kisfgv1() es kisfgv2() "wrapper" fuggvenyek, amiknek van statikus valtozoja, ebbe fog belekerulni a fofuggveny()-ben kiszamolt ertek. Igy ahany helyrol akarod hivni a fofuggvenyt, annyi kisfgv()-t tudsz letrehozni, kulonbozo ertekeket fognak tarolni, mig a fofuggveny()-t nem kell modositanod. Csak ezutan a kisfgv()-ket kell majd hivogatni, nem a fofuggvenyt()-t. A main()-ban pedig az stvaltozo erteke a fuggvenyhivas utan megkapja az erteket a helyi statikus valtozonak, nem kell hogy azok globalisak legyenek.

Ha jol ertettem, hogy mit akarsz, es nem irtam el semmit, akkor ez is egy megoldasa a problemanak, csak osztalyok nelkul.

--
ahan nem

Na, _pont ezt_ szeretném elkerülni :)
Abban igazad van, hogy ez nagyjából azt csinálja amit szeretnék, de ez azért nem jó, mert nem adaptív. Ha egy "új" hívást szeretnék, akkor kell hozzá egy kisfgv(..)-t is írni. Ezt nem akarom, mert:
- sok példány kell(ene), ráadásul előre nem tudom, hogy mennyi
- meghízik a kód
- hibalehetőség
- osztályra valószínűleg ígyis-úgyis szükségem lesz az absztarkció miatt
- nem szép