- Karácsonyfaként világíthat a Thermaltake új CPU-hűtője
- Az USA vizsgálja a RISC-V kínai terjedésének kockázatát
- Kicsit extrémre sikerült a Hyte belépője a készre szerelt vízhűtések világába
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Kihívás a középkategóriában: teszten a Radeon RX 7600 XT
- Azonnali informatikai kérdések órája
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Milyen asztali (teljes vagy fél-) gépet vegyek?
- Autós kamerák
- Intel Core i5 / i7 / i9 "Alder Lake-Raptor Lake/Refresh" (LGA1700)
- Gaming notebook topik
- Milyen videókártyát?
- Házimozi haladó szinten
- Milyen TV-t vegyek?
- VR topik (Oculus Rift, stb.)
Hirdetés
-
Spyra: akkus, nagynyomású, automata vízipuska
lo Type-C port, egy töltéssel 2200 lövés, több, mint 2 kg-os súly, automata víz felszívás... Start the epic! :)
-
Saját Redmi Note 13 Pro+ a világbajnok focicsapatnak (és indiai rajongóiknak)
ma Argentína nemzeti válogatottjának mezével díszítik az új Redmi különkiadást.
-
Az USA vizsgálja a RISC-V kínai terjedésének kockázatát
ph A Kereskedelmi Minisztérium egyelőre csak felméri a helyzetet, egyelőre nem látni, hogy tudnak-e bármit is tenni.
Új hozzászólás Aktív témák
-
jattila48
aktív tag
válasz choco01 #4050 üzenetére
tanulo.nev = "Tamas";
helyetttanulo->nev = "Tamas";
sorral próbálkozzál. Úgy jónak kell lenni. Mivel new-val hoztad létre az objektumot, egy erre mutató pointert kaptál vissza (mint ahogy helyesen így is deklaráltad a tanulo változót), aminek a tartalma (*tanulo) maga az objektum, és ennek van nev nevű adattagja. Ezért így is írhattad volna:(*tanulo).nev = "Tamas";
De mivel annyira gyakori konstrukcióról van szó, a rövidség kedvéért err bevezették a -> operátort.[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
choco01
addikt
válasz jattila48 #4051 üzenetére
És ha csak simán így csinálom az mivel rosszabb?
int main()
{
iskola tanulo;
tanulo.nev = "Tamas";
cout << tanulo.nev;
system("pause");
return 0;
}szóval kihagyom a new iskolás részt..
[ Szerkesztve ]
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
b.kov
senior tag
válasz choco01 #4052 üzenetére
Nem rosszabb semmivel, azonban ekkor a stack-en jön létre az objektum, ahogy írták is korábban.
Amíg nem indokolt pointerek használata, addig egyébként is érdemes kerülni őket. Majd ha belemerülsz jobban a témába, és szembe jön veled a dinamikus kötés, referencia szerinti paraméterátadás, öröklődés, stb... akkor érdemes foglalkozni jobban a pointerekkel is. Addig tanulgatni teljesen jó ez a módszer is, ahogyan most csinálod.
-
choco01
addikt
Most ilyen speedrun megy mert holnap írunk ZH-t és leragadtam a struktúráknál, de elvileg kötelező lesz osztályokat használni.. úgy hogy amennyit csak tudok olvasok..
A gyakorló feladat ilyesmi volt, végülis értem, csak pár apró része nem világos hogy miért oda miért nem, eddig úgy gondoltam hogy a private/protected rész arra kell hogy mások elől védjem az ott lévő dolgokat és akkor valahogy publicba tudok infót adni a védett részbe is..de aztán lehet nem..
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
/*Készítsen programot, melyben a Kétkerék nevű kerékpár kölcsönző adatait tudja kezelni.A kölcsönzőben kétféle
típusú kerékpár van, melyek kölcsönzési óradíja különböző.A magellan 1200 Ft / óra, a median 1000 Ft / óra.
A kolcsonzo.txt szöveges állomány első sorában a kölcsönzések számát, a kölcsönzések adatait a következő struktúra szerint tartalmazza:
struct kolcsonzes
{
string; //a kölcsönzés napja
string tipus; //a kerékpár típusa
int sorszam; //a kerékpár sorszáma
int ido; //a kölcsönzés ideje
};
Készítse el az alábbi függvényeket, mindegyik függvény vegye át az állomány nevét :
Getdb() Adja vissza az adatok számát.
GetMagellan() Adja vissza a magellan kerékpárok számát.
GetMedian() Adja vissza a median kerékpárok számát.
MedianBevetel() Adja vissza a median kerékpárokkal szerzett bevétel összértékét.
OsszBevetel() Adja vissza a bevétel összértékét.
LeghosszabbKolcsonzes() Adja vissza a leghosszabb kölcsönzés adatait tartalmazó struktúrát.
Kiir() A függvény minden adatot sorszámozva, az kiíratja a képernyőre táblázatos formában, minden struktúra egy
sorba kerüljön(a sorszám 1 - ről indul).
*/
struct kolcsonzes
{
string datum;
string tipus;
int sorszam;
int ido;
};
class kolcsonzo
{
private:
kolcsonzes *k;
int db;
public:
kolcsonzo(char fnev[]);
~kolcsonzo();
int Getdb();
int GetMagellan();
int GetMedian();
int MedianBevetel();
int Osszbevetel();
int LeghosszabbKolcsonzes();
void Kiir();
};
//kolcsonzo.txt beolvasasa
kolcsonzo::kolcsonzo(char fnev[])
{
ifstream be(fnev);
if (be.fail()) { cerr<<"hiba fajlnyitas"; system("pause"); exit(-1);}
be >> db;
k = new kolcsonzes[db];
if (k == 0) { cerr << "hiba2";system("pause");exit(-2);}
for (int i = 0; i < db; i++)
{
be >> k[i].datum;
be >> k[i].tipus;
be >> k[i].sorszam;
be >> k[i].ido;
}
be.close();
}
kolcsonzo::~kolcsonzo()
{
if (k != 0)
delete[]k;
}
int kolcsonzo::Getdb()
{
return db;
}
int kolcsonzo::GetMagellan()
{
int m = 0;
for (int i = 0; i < db; i++)
{
if (k[i].tipus=="magellan")
{
m++;
}
}
return m;
}
int kolcsonzo::GetMedian()
{
int m = 0;
for (int i = 0; i < db; i++)
{
if (k[i].tipus=="median")
{
m++;
}
}
return m;
}
int kolcsonzo::MedianBevetel()
{
int mbev = 0;
for (int i = 0; i < db; i++)
{
if (k[i].tipus=="median")
{
mbev += k[i].ido * 1000;
}
}
return mbev;
}
int kolcsonzo::Osszbevetel()
{
int bev = 0;
for (int i = 0; i < db; i++)
{
if (k[i].tipus=="median")
{
bev += k[i].ido * 1000;
}
else
{
bev += k[i].ido * 1200;
}
}
return bev;
}
int kolcsonzo::LeghosszabbKolcsonzes()
{
int l = k[0].ido;
for (int i = 0; i < db; i++)
{
if (k[i].ido > l)
{
l = k[i].ido;
}
}
return l;
}
void kolcsonzo::Kiir()
{
cout << setw(14) << "datum" << setw(20) << "tipus" << setw(10) << "sorszam" << setw(10) << "kolcsido" << endl;
for (int i = 0; i < db; i++)
{
cout << i + 1 << "." << setw(12) << k[i].datum << setw(20) << k[i].tipus << setw(10) << k[i].sorszam << setw(10) << k[i].ido << endl;
}
}
int main()
{
kolcsonzo ketkerek("kolcsonzo.txt");
cout << "Az allomanyban levo adatok:\n";
ketkerek.Kiir();
cout << endl;
cout << "A kolcsonzesek szama: " << ketkerek.Getdb() << endl;
cout << "A magellan kolcsonzesek szama: " << ketkerek.GetMagellan() << endl;
cout << "A median kolcsonzesek szama: " << ketkerek.GetMedian() << endl;
cout << "A median kerekparokkal szerzett bevetel: " << ketkerek.MedianBevetel() << endl;
cout << "A kerekparokkal szerzett osszbevetel: " << ketkerek.Osszbevetel() << endl;
cout << "A leghosszabb kolcsonzes ideje: " << ketkerek.LeghosszabbKolcsonzes() << endl;
cout << endl << endl;
cout << "***************** dinamikus objektum *****************\n\n";
kolcsonzo *kektura = new kolcsonzo("kolcsonzo.txt");
if (kektura == 0)
{
cerr << "keves a memoria 2";
return 2;
}
cout << "Az allomanyban levo adatok:\n";
(*kektura).Kiir();
cout << endl;
cout << "A kolcsonzesek szama: " << kektura->Getdb() << endl;
cout << "A magellan kolcsonzesek szama: " << kektura->GetMagellan() << endl;
cout << "A median kolcsonzesek szama: " << kektura->GetMedian() << endl;
cout << "A median kerekparokkal szerzett bevetel: " << kektura->MedianBevetel() << endl;
cout << "A kerekparokkal szerzett osszbevetel: " << kektura->Osszbevetel() << endl;
cout << "A leghosszabb kolcsonzes ideje: " << kektura->LeghosszabbKolcsonzes() << endl;
cout << "Az 5 oranal hosszabb kolcsonzesek:\n";
delete kektura;
system("pause");
return 0;
}Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
b.kov
senior tag
válasz choco01 #4054 üzenetére
Ha van valami konkrét kérdésed, akkor írd nyugodtan, de egyébként jól látod szerintem a dolgokat.
Ha nincs öröklődés, akkor a protectedet felejtsd el egy kicsit, és csak a public-private részre koncentrálj.Nagyon egyszerűen tényleg csak annyi a dolog, hogy a privát adattagokhoz/függvényekhez kintről (az osztály példányain keresztül) nem lehet közvetlenül hozzáférni. Ez ugye az enkapszuláció lényege, előttem jól meg lett fogalmazva.
-
choco01
addikt
Igen van továbbra is az ami az elején..
ez a *k dolog azaz hogy
kolcsonzes *k;
sor miért kell a privátba?
a kolcsonzes struktúrára mutat a k? vagy hogy értelmezzem?mert utána visszatér ugye az előbb írt kódban a
k = new kolcsonzes[db];
meg utána a feltöltés is a k-ra megy..Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
choco01
addikt
válasz choco01 #4056 üzenetére
Továbbá ezt sem értem hogy miért nevezzük ezt a konstruktornak:
kolcsonzo(char fnev[]);
mert hát más is néz ki ehhez hasonlan.. pl.:int GetMagellan();
és akkor ehhez is lehetne egy~GetMagellan();
-t destruktornak írni..? mivan ha nem csinálok konstruktort hanem csakint kolcsonzo(char fnev[]);
-et írok?bocs a dupláért..
[ Szerkesztve ]
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
b.kov
senior tag
válasz choco01 #4056 üzenetére
Ennek a pointernek a segítségével hozod létre az egyes kölcsönzőkhöz tartozó tömböket, amiknek az eleme "kolcsonzes" típusúak. Tehát ha pontosabbak akarunk lenni, akkor azt is lehet mondani, hogy a k pointered ennek a tömbnek a fejelemére mutat. A
k[i]
pedig a fejelemtől i. távolságra lévő elemre.Ennek a pointernek pontosan azért kell privátnak lennie, mivel minden egyes "kolcsonzo" példány létrehozásával egy file-ból olvasod be a kölcsönzéseket. Ezek ugye statikus adatok, amiken később nem szeretnél vátloztatni. Tehát ne lehessen azt mondani, h pl. "mintaKolcsonzo" objektumon keresztül, a 3. kolcsonzés idejét megváltoztatod. Tehát:
kolcsonzo mintaKolcsonzo("inputFile_1");
Ekkor beolvasod ugye a fájlból a statikus adatokat. Nem lenne jó, ha ezután tudnál ilyet csinálni:
mintaKolcsonzo.k[2]->datum = "Buddha szobor";
Persze létezik igény fájlból beolvasott adatok utólagos módosítására (sőt), viszont ez akkor sem szép megoldás. Arra külön setter függvényeket szokás írni, csakúgy mint a mostani getter függvények.
Tehát az előző példában ha megengednénk a dátum módosítását, akkor így lenne mondjuk szép:
mintaKolcsonzo.modifyDate(2, "2018.02.03");
Ahol ez első paraméter a kölcsönzés száma, a második pedig az új kölcsönzési dátum.[ Szerkesztve ]
-
choco01
addikt
De most akkor azt is lehetne írni a feltöltéskor hogy
kolcsonzes[i].datum;
és a többi? minek akkor ez a k-s dolog.. meg hogyan tehetem a private tagokat elérhetővé más számára? valamilyen értékátadásról beszélt a Tanár Úr az egyik órán, de nem értettem teljesen..volt valami friend függvény is.. ezeket csak így elmondják aztán nem használtuk, de azért van..cattus:
Köszönöm, most belenéztem, de ebbe hogyhogy strukturákon csinálja a private meg public dolgokat..
[ Szerkesztve ]
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
dabadab
titán
válasz choco01 #4060 üzenetére
C++-ban a struct meg a class ugyanaz a dolog, két különböző névvel. Az egyetlen különbség a default láthatóság, vagyis ha nem írod ki, hogy public: meg private: (de úgyis kiírod), akkor classnál defaultból minden private, structnál meg minden public. Szóval gyakorlatilag az classt meg a structot lehetne egymás helyett használni (de ne csinálj ilyet, mert csak összezavarsz vele másokat (meg a jövőbeli magadat )
"meg hogyan tehetem a private tagokat elérhetővé más számára?"
A private pont azért private, hogy ne legyen elérhető más számára Ha ezt akarod, akkor legyen public, de alapvetően adattagotkat nem jó ötlet publicra rakni, mert akkor mindenki úgy rondít bele, ahogy nem szégyell - inkább legyenek a más osztályok számára érdekes adatok tagfüggvényeken keresztül, mert így egyrészt tudod ellenőrizni az értékadásokat, hogy nem hülyeséget akar-e a másik beleírni, illetve át tudod faragni a belső adatstruktúrát anélkül, hogy emiatt át kellene írni a többi osztályt is.
(A kivétel az, ha tisztán adatokat (függvényeket viszont nem) tartalmazó osztályt kell létrehozni, ott publicra érdemes rakni a tagokat és ezeknél érdemes a struct kulcsszót használni, hogy mindenki elsőre lássa, hogy miről van szó)
[ Szerkesztve ]
DRM is theft
-
dabadab
titán
válasz choco01 #4057 üzenetére
"ovábbá ezt sem értem hogy miért nevezzük ezt a konstruktornak: kolcsonzo(char fnev[]); mert hát más is néz ki ehhez hasonlan.. pl.: int GetMagellan();"
Két fontos különbség van a kolcsonzo() meg a GetMagellan() között:
1. a konstruktort pontosan úgyanúgy hívják mint az osztályt
2. nincs visszatérési értéke (még void se)"mivan ha nem csinálok konstruktort hanem csak int kolcsonzo(char fnev[]);-et írok?"
Reklamálni fog a fordító, hogy konstruktornak nem adhatsz meg visszatérési értéket (az meg, hogy konstruktor, onnan jön, hogy pont úgy hívják, mint az osztályt)
DRM is theft
-
dabadab
titán
Egyébként meg most komolyan, char*, C tömbök meg tök felesleges new/delete egy C++-t illusztráló iskolai példaprogramban? Tényleg már csak egy gets() hiányzik.
[ Szerkesztve ]
DRM is theft
-
jattila48
aktív tag
válasz choco01 #4060 üzenetére
Ahogy b.kov leírta, k a kölcsönzéseket tároló tömb, ami kolcsonzes * típusú (vagyis kolcsonzes tipusu strukturara mutató pointer). Ez azért pointer, (és nem tömb, de tömbként lesz használva), mert előre nem tudod, hogy hány darab kölcsönzést fog tartalmazni (ezt is fájlból olvasod be a db változóba), tömböt deklarálni pedig csak konstans mérettel lehet. Ha megvan hogy hány darab kölcsönzést tartalmaz a fájl, akkor ekkora méretű tömböt fogsz dinamikusan (new-val) lefoglalni, ami kolcsonzes * típusú pointert ad vissza. Talán az okozza a zavart, hogy nem érted miért kell pointer, ha egyszer tömbbe olvasol be. A C-ben (és C++-ban) pointereket lehet tömbszerű szintaxissal használni (ki lehet indexelni mint a tömb elemet), illetve a tömb neve (indexelés nélkül) a tömb kezdőcímét jelenti. A tömb indexelés tulajdonképpen nem más, mint a kezdőcímhez képest indexszel eltolt pointerre való dereferencia. Tehát tomb ugyanaz, mintha *(tomb+i) -t írnál (ez pedig ugyanaz mint *(i+tomb), ami ugyanaz mint i[tomb]; egy kis nyalánkság a C szintaxisból). Ahogy fent írtam, csak a dinamikus helyfoglalás miatt kell pointer, és nem tömb. Ha azt gondolnád, hogy ilyen módon a pointer és a tömb tulajdonképpen ugyanaz, akkor nem lenne egészen igazad, ugyanis a tömb név (mint a tömb kezdő címe) konstans pointer (fordítás idejű konstans), ezért nem lehet neki értéket adni, és nem lehet a címét képezni, ellentétben a pointer típusú változóval. Elég baj, hogy a C-ben a tömb és pointer fogalma így összemosható, ebből szoktak félreértések (és hibák) adódni. Ennyit a tömbökről.
Hogy miért private ez a tömb (pointer), az pedig azért, mert nem feltétlenül kellene a kölcsönzéseket tömbben tárolni (lehetne pl. lista), ezért az osztályod felhasználója nem kell (nem szabad) hogy tudjon az implementációról, számára elég a publikusan biztosított tagfüggvények ismerete, ami az implementációtól függetlenül mindíg ugyanúgy hívható (ez OOP alapelv).
"De most akkor azt is lehetne írni a feltöltéskor hogykolcsonzes[i].datum
;"
Ebben a sorban nem csináltál semmit, egyszerűen a stackre helyezted akolcsonzes[i].datum
értékét.
"hogyan tehetem a private tagokat elérhetővé más számára?"
Leginkább public tagfüggvények által, magát a private adatszerkezetet nem szokás (hiszen ezért private). Ha feltétlenül elérhetővé akarod tenni, akkor legyen public. Előfordulhat azonban, hogy bizonyos külső (free vagyis nem tfv.-ek) függények számára meg akarod engedni a private/protected adattagok elérését, akkor az osztályod ezeket a fv.-eket friend-ként deklarálja (komplett osztályt is lehet friend-ként deklarálni). A friend deklaráció nem esik a public, private, protected láthatóság hatálya alá, mindegy hová írod. Mindíg az az osztály fogadhat barátjának egy fv.-t (vagy másik osztályt), amelyik ezek számára meg akarja engedni a private tagjainak elérését. Nem fordítva, tehát egy külső fv. nem jelentkezhet be, hogy szeretné az adott osztály private tagjait elérni.
A struktúra és az osztály között összesen az a különbség, hogy a struktúra tagjai default public elérésűek, míg az osztályé default private. Vagyis ha nem írsz ki láthatóságot, akkor ez vonatkozik a tagokra. Más különbség nincs, ettől eltekintve teljesen ugyanúgy használhatók. Szokás szerint, ha csak adattagok vannak, akkor struktúrát használnak, ha tfv.-ek is vannak, akkor osztályt, de ez csak konvenció.u.i.: közben míg írtam a választ dabadab megelőzött, kb. ugyanazt válaszolta.
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz jattila48 #4065 üzenetére
"Tehát tomb ugyanaz, mintha *(tomb+i) -t írnál"
Átvált italic betűtipusra mikor azt akartam írni, hogy:
Tehát tomb[j] ugyanaz, mintha *(tomb+j) -t írnál..
Most az i indexet j-re írtam át, remélem így elfogadja.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
choco01
addikt
válasz dabadab #4061 üzenetére
Zsír akkor értem a class és struct közötti különbségeket, köszönöm!
Ugye az nem világos hogy minek csináljak private tagokat ha akkor lényegében azzal nem tudok semmit sem tenni.. az csak van mindentől elszigetelve és kész, a példa kódomban ugye ez van:
private:
kolcsonzes *k;
int db;Na most itt akkor nem sok értelmét látom mert ezzel nem tudok mit kezdeni? Bár ha végig nézem a konstruktorba még is csak hivatkozik a k-ra, akkor a konstruktor még is látja a private dolgokat?
Általában emeltszintű érettségi példák vannak kidolgozva és azokat csináljuk meg..
all:Az miért van hogy mindig dinamikus tömböket használunk amikor tudjuk előre is hogy hány elemű lesz?Azt hiszem néztünk olyan példát előadáson hogy volt benne dinamikustömb de konkrétan megadva az elemszámmal.. vagy ennél a classon témánál mindig ez kell?
Meg ugye a dinamikus tömbkezelésre ezt tanultuk:
<típus>* név = new <típus>[érték];
Most az előző példakódomban ez volt:k = new kolcsonzes[db];
itt se típus se * nincs az elején a másik végén meg típus nincs.. akkor honnan tudja hogy ez dinamikus?jattila48:
Neked is köszönöm, így már kezd összeáállni, valahogy gyakarolnom kéne, próbálok keresni rá még példát a suliban majd.. Így ennél a példámnál értem hogy ezért kell dinamikus meg hogy a beolvasáskor tudjuk meg hogy hány elemű lesz!
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
jattila48
aktív tag
A private tagokat nem csak a konstruktor, hanem az összes tagfüggvény eléri. A tagfüggvények elől nincs elzárva a private tag, csak a külső (nem tfv.) függvények elől. Sőt ugyanannak a típusnak másik példánya is hozzáfér a private/protected tagokhoz (pl. egy olyan tfv., ami argumentumban másik ugyanolyan típusú példányt (vagy pointert/referenciát) kap, szintén gond nélkül eléri az argumentumban kapott objektum private/protected tagjait).
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
choco01
addikt
válasz jattila48 #4069 üzenetére
Gondolom ez nekem jött, szóval akkor amiket betettem a publicba függvényeket, pl. getMagellan() azokban amikor kifejtem hogy mit is csináljanak ott felhasználhatom a private dolgokat?
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
jattila48
aktív tag
-
choco01
addikt
Köszi mindnekinek!! Sikerült!!
Applikáció fejlesztés, weboldal készítés, SEO, Online marketing » https://petadev.com
-
jattila48
aktív tag
C++ -ban nincs lehetőség closure definiálásra, az Embarcadero (Borland) azonban megoldotta ezt a __closure kulcsszó bevezetésével. Szerintetek hogy lehetne sima C++ -ban szimulálni a closure-t? A C++ keretein belül nyilván sehogy, erre kellet a __closure kiterjesztés. De vajon hogy oldják ezt meg a mélyben? Szerintem fordítás/linkelési időben ezt nem lehet, valószínűleg futás közben generálják le a closure végrehajtható kódját (legalábbis egy forwarding fv. kódját), és ezt futtatják. Ehhez azonban Windowsban VirtualProtect-tel futtathatóvá kell tenni azt a memóriaterületet, ahová a kód kerül. Mit szólnak ehhez a vírusirtók?
Ha esetleg valaki nem tudja mi a closure: egy objektum tagfüggvényére mutató fv. pointer. Nem azonos a C++ tfv. pointerével, mert az egy sima fv. pointer, ami történetesen az osztály tfv.-re mutat (fordítás idejű konstans), és csak az osztályból létrehozott objektumon keresztül lehet meghívni. A closure azonban az adott objektumot (a this pointert) "magába olvasztva" (mint konstans értéket) tartalmazza, és csak a this pointeren kívüli argumentumok az argumentumai. Ezáltal alkalmassá valik callback fv. pointerként való használatra (ez a lényeg).„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz jattila48 #4073 üzenetére
Egy szimuláció a következő lehet:
class Akarmi{
public:
Akarmi(int x):a(x){}
int addto(int x){
return a+x;
}
private:
int a;
};
Akarmi *pa;
int closure_func(int x){
return pa->addto(x);
}
void main(int argc,char *argv[]){
pa=new Akarmi(5);
std::cout << closure_func(6);
}A fenti példában closure_func 5-öt ad hozzá az argumentumához. és nem tfv., címe pedig használható lenne callback fv. pointerként. A gond csak az, hogy ha szükségem lenne egy 11-et hozzáadó closure-re is, akkor létre kéne hozni egy globális Akarmi(11) objektumot is (pl. pa11 nevu pointerrel), és definiálnom kéne egy closure_func11-et, ami a pa11-gyel hívja az addto tfv.-t. Ez nem túl jó megoldás. Amikor előző hozzászólásomban azt írtam, hogy futás közben kódot generálnak, akkor arra gondoltam, hogy kb. ezt a konstrukciót hozzák létre. Amikor létrejön az Akarmi(5) objektum, annak címével (mint konstanssal, vagyis a generált kódban ezt a címet "bedrórozva" konstansként használják) legenerálják a closure_func kódot, és closure fv. pointerként pedig visszaadják a röptében generált kód kezdőcímét. Így talán világosabb mire is gondoltam.
Várom a hozzászólásokat!„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
static member function nem jó, mert az nem éri el az osztály nem static tagjait, nekem pedig erre lenne szükségem. A static member function kb. ugyanaz (legalábbis ilyen szempontból), mint egy közönséges free fv.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz EQMontoya #4077 üzenetére
Lambdát nem tudsz átadni callback fv. pointerként pl. egy CreateThread vagy StartServiceCtrlDispatcher api hívásnak. Ezek egyetlen pointert várnak, a lambda pedig egy C++ nyelvi konstrukció (a mélyben egy névtelen osztály konstruktorral,...), amit az api fv. nem fog tudni értelmezni.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
-
jattila48
aktív tag
válasz EQMontoya #4080 üzenetére
A CreateThread-et csak példának hoztam. C++ -ban is előjöhetnek hasonló problémák, pl. különböző objektumok (pl. nyomógomb) tfv.-eit mint üzenetkezelő callback fv.-t kell regisztrálni.
Nem kikerülni, hanem megérteni szeretném a problémát, úgyhogy ne a kikerülésére tegyetek javaslatot. Azt nyilván magam is meg tudom tenni, ha arra van szükségem.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
PandaMonium
őstag
válasz jattila48 #4081 üzenetére
Ahogy már mondták, használj lambdát capture-el. std::function-ben tudod tárolni a lambdádat és továbbadni akár paraméterként. Capture nélüli egyszerű példa:
int main()
{
std::function<int()> x = []() { return 42; };
std::cout << x() << std::endl;
return 0;
}What I cannot create, I do not understand
-
jattila48
aktív tag
válasz PandaMonium #4082 üzenetére
És szerinted ez az std::function egy 32/64 bites fv. pointer lesz, amit assemblyben call eax -szel meg tudok hívni? Mert szerintem nem, de erre válaszoltam EQMontoyanak is. API fv.-nek szeretném átadni, mint callback fv. pointert, aminek fogalma sincs az std::function mibenlétéről. Az egy objektum, amit a ctor.-a másol a stackre, ha argumentum-ként adod át. Mit kezdjen ezzel egy API fv?
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz EQMontoya #4084 üzenetére
Milyen API fv. kezel C++ template-eket 2018-ban? Ne beszélj már butaságokat! Tudod mi az az API? Az egy bináris interfész az op. rendszer felé. C++ -ban forráskód szinten használhatók az ilyen konstrukciók, mert a c++ fordító a template-eket megfelelően lefordítja a template argumentumok típusának megfelelő forráskódra, majd azt bináris kódra. Egy bináris interfész-hez hogy akarod ezt illeszteni?
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
PandaMonium
őstag
válasz jattila48 #4083 üzenetére
Ha kinyitod a cppreference.com-ot akkor látod, hogy az std::function
T* target() noexcept;
metódusával visszakapod a függvény pointert amit úgy hívsz meg ahogy akarsz. Ha nem észt osztani járnál ide (főleg miután te kérsz segítséget), hanem utána olvasnál a dolgoknak előrébb lennél.What I cannot create, I do not understand
-
dobragab
addikt
válasz jattila48 #4081 üzenetére
Ha capture list van a lambdadban, akkor nem tudod belole siman kikerni a fuggvenypointert. Szerencsere van ra trukk Ez a standard
signal
-t hivja meg, ami valoban egy pattintott fuggvenypointert var.std::function<void(int)> sh = [capture](int sig) {
std::cout << "Signal " << sig << " caught, captured " << capture << std::endl;
};
signal(SIGINT, tmp_lib::to_fptr(sh, []{}));(#4086) PandaMonium
target()
sem jo, ha objektumot capture-oltel, akkor a target nem lesz soha fuggvenypointer.[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
Dinter
addikt
Sziasztok.
Lenne egy függvényem, amivel txt-be íratnám ki az adatokat, ezerféle variációt kipróbáltam már, de sose csinál semmit..
#include <iostream>
#include <fstream>
...void ment() {
std::ofstream file;
file.open("adatok.txt");
file << "Teszt";
file.close();
} //kiír fájlbaMit rontok el?
-
EQMontoya
veterán
file.open("akarmi.txt", std::ofstream::out)
Próbáld így.
Illetve van egy is_open() függvénye az ofstreamnek, azzal meg tudod nézni, hogy egyáltalán sikerült-e megnyitni az output filet, vagy pl. olyan helyre próbálsz írni, ahová nem tudsz...
[ Szerkesztve ]
Same rules apply!
-
Dinter
addikt
Van valami scanf-hez hasonló függvény, amivel megadhatom, milyen formában olvassa be az adatokat? Tehát megvan a sorom stringbe beolvasva, a részek tabulátorral elválasztva, és a tabulátorok közötti részt további stringekbe darabolni.
-
-
EQMontoya
veterán
-
b.kov
senior tag
Hát akkor tényleg azt tudom mondani, hogy bekéred az első sorban az adatot, h melyik konstruktornak kell lefutnia, aztán az alapján annyit olvasol std::cin-nel, ahány paraméteres a kiválasztott konstruktor.
Igazából ha nem engednek STL konténereket (meg gondolom algoritmusokat sem), akkor talán ez a legegyszerűbb módszer.
szerk.: a scanf-es megoldás, meg vagdosás sokkal inkább favágómódszernek tűnik nekem
[ Szerkesztve ]
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Mobilinternet
- Kerékpárosok, bringások ide!
- EA Sports WRC '23
- Videó stream letöltése
- Azonnali informatikai kérdések órája
- Ubiquiti hálózati eszközök
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Motorola Edge 40 neo - színre és formára
- Milyen asztali (teljes vagy fél-) gépet vegyek?
- Autós kamerák
- További aktív témák...