- 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
- Gaming notebook topik
- Mini-ITX
- A régi node-okra koncentrál a szankciók miatt Kína
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Sony MILC fényképezőgépcsalád
- AMD K6-III, és minden ami RETRO - Oldschool tuning
- Micro Four Thirds
- Azonnali informatikai kérdések órája
- Házimozi, és Hifi kábelezés!
- ASUS ROG Ally
Hirdetés
-
Megjelenési dátumot kapott a Star Wars: Hunters
gp A tervek szerint június elején végre befut a teljes kiadás mobilokra/tabletekre és Nintendo Switch-re.
-
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.
-
Samsung Univerzum: Így ismerhető meg a Galaxy AI bármilyen telefonon
ma A Try Galaxy webalkalmazás kontrollált környezetben mutatja meg, mit tud a One UI 6.1-es rendszer és a mesterséges intelligencia.
Új hozzászólás Aktív témák
-
jattila48
aktív tag
válasz jattila48 #4150 üzenetére
Igazából a globálisan deklarált const int hasonló mint a static const int, úgyhogy arra is igaz amit eddig írtam. A lokális const int-hez valóban tartozik memóriacím.
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
Teasüti
nagyúr
Tehát ami nekem átjött ebből a beszélgetésből, hogy ha new operátorral hozok létre tömböt (foglalok le dinamikus memóriát), akkor az egy ún. heap-re kerül, míg ha new nélkül, akkor a stack-be.
Ez így korrekt? Van egyéb gyakorlati jelentősége?
Köszönöm! -
jattila48
aktív tag
válasz Teasüti #4153 üzenetére
"Tehát ami nekem átjött ebből a beszélgetésből, hogy ha new operátorral hozok létre tömböt (foglalok le dinamikus memóriát), akkor az egy ún. heap-re kerül,..."
Ez igaz.
"...míg ha new nélkül, akkor a stack-be."
Ez nem feltétlenül igaz, mert a globális adatterületen is deklarálhatsz tömböt.
Egyéb gyakorlati jelentősége pedig az, amit eddig leírtam. Röviden összefoglalva:
- A tömb név nem változó, nem adhatsz neki értéket, és nem képezheted a címét.
-A pointer változó, ami memória címet tartalmaz (pl. a heapen lefoglalt memória címét, de lehet más pl. "hagyományosan" deklarált tömb címe is). A pointer értéke megváltoztatható, és a címe is képezhető.
-Tömböt csak konstans méretűt deklarálhatsz (kivéve C99), míg new-val változó méretű memóriát foglalhatsz.
-Tömböt nem szabad felszabadítani, new-val létrehozott memóriát pedig fel kell szabadítani.
Kb. ennyi ami gyakorlatban különbség a két fogalom között, és amiről minden programozónak tudnia kell.
Még egy "apróság": C++ -ban tömb név, mint konstans pointer lehet template argumentum (mivel fordítási időben kiértékelhető), pointer viszont nem (mivel csak futási időben értékelhető ki).[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz Teasüti #4155 üzenetére
Amit lehet a stacken jobb tartani(gyorsabb, nem kell delete), a nagy méretű adatot meg heap-en(van neki hely gazdagon).
A new+delete párra meg vannak osztályok, amikbe becsomagolva megkapod az eltakarítást.
std::vector a dinamikus tömbhöz, std::unique_ptr, std::auto_ptr egyéb mutatóhoz.
Ezek az osztályok a delete-et úgy oldják meg, hogy a destruktorukban meghívódik az általuk tárolt pointerre a delete.
És ezeket a pointer "wrapper"-eket pedig stack-en tartod valahol és amikor elhagyod a scope-ot, szépen lefut a destruktor és magától felszabadul a memória.
Ez azért nagyon fontos, mert minden programozó hibázik és nem igazán függ a hibázás gyakorisága attól, hogy mióta űzöd a mesterséget. Ezzel védjük magunkat a memory leak-től.A vector persze elsődlegesen nem pointer wrapper, arra találták ki, hogy nagyon kényelmesen legyen egy bármikor átméretezhető tömböd. A belsejében egy dinamikus tömb van.
-
jattila48
aktív tag
-
m.zmrzlina
senior tag
A string osztálynak van két tagfüggvénye a size() és a .length()
Azt olvasom itt:
Both string::size and string::length are synonyms and return the same value.Kérdésem, hogy miért kell két teljesen azonos tagfüggvény?
-
doc
nagyúr
válasz m.zmrzlina #4159 üzenetére
gondolom azert van size() hogy a tobbi containerrel interface-kompatibilis legyen, a length() meg azert, mert stringnel az logikus
-
PandaMonium
őstag
válasz m.zmrzlina #4159 üzenetére
Pl.
#include <iostream>
#include <vector>
#include <string>
template<typename T>
std::size_t sizeOfContainer(const T& container) {
return container.size();
}
int main()
{
std::vector<int> x = { 1, 2, 3 };
std::string y = "foobar";
std::cout << sizeOfContainer(x) << std::endl;
std::cout << sizeOfContainer(y) << std::endl;
return 0;
}Ez a kódrészlet nem működne a string-en, ha nem lenne size függvénye, külön template specializációt kéne rá írni. Egyébként ahogy már írták elsősorban azért van size() függvénye, hogy hasonlítson a containerek intefészére, elvégre a string csak egy karakter container (iterátorai is vannak).
What I cannot create, I do not understand
-
m.zmrzlina
senior tag
válasz PandaMonium #4161 üzenetére
Köszönöm. Nem állítom hogy minden részletét értem de egy kicsit beljebb vagyok.
-
Ron Swanson
senior tag
Sziasztok!
Van egy feladat, amit nem tudok megoldani, és örülnék egy kis segítségnek.
Ez lenne a feladat: KÉPOdáig eljutottam, hogy megadtam a változókat és bekértem azokat:
#include <iostream>
using namespace std;
int main()
{
int orhelyekSzama;
int orsegekSzama;
cin >> orhelyekSzama;
cin >> orsegekSzama;
int sorszam[orhelyekSzama];
for(int i=1; i<orhelyekSzama; i++){
cin >> sorszam[i];
}
}Még csak a nagyon alapokat tanultuk: if else, for ciklus, tömbök. Szóval egyszerű feladat, de mégsem tudom folytatni
[ Szerkesztve ]
-
EQMontoya
veterán
válasz Ron Swanson #4163 üzenetére
Neked nem c++ kerdesed van, hanem algoritmikai, adatszerkezeti,
Eloszor is gondolkozz.
Tarolnod kellene valahol az orhelyeket. Mondjuk tombben, mert azt tudod indexelni.
Tehat beolvasol egy orseget (ami egy szam), azzal indexeled a tombot, igy oda be tudsz rakni egy orseget.Neked nem a
sorszam[I]
-be kell beolvasnod, hanem beolvasol egy intbe, es azzal indexeled a tombot.Utana meg kell talalnod, hogy hogyan lehet optimalisan lefedni az egeszet. Ehhez gondolkodni kell kicsit, de gondolkodni nem fogunk helyetted, a c++ reszeben segitunk szivesen.
[ Szerkesztve ]
Same rules apply!
-
Ron Swanson
senior tag
Az előző problémát megoldottam, viszont most ismét szükségem lenne egy kis segítségre. (Ez már egy másik feladat.)
Van ez a kódom:
#include <iostream>
#include <vector>
class TVendegek
{
public:
int erkezes;
int tavozas;
TVendegek(const int E, const int T):
erkezes(E), tavozas(T) {}
const bool talalkoztak(const TVendegek & g) const;
const int tartozkodasiIdo() const {
return tavozas > erkezes;
}
};
const bool TVendegek::talalkoztak(const TVendegek & g) const
{
const TVendegek * a;
const TVendegek * b;
if (this->erkezes > g.erkezes) {
a = &g;
b = this;
} else {
a = this;
b = &g;
}
return (a->tavozas >= b->erkezes);
}
int main()
{
using namespace std;
int N, i, Ei, Ti;
vector<TVendegek> vendegek;
int max_index, max_darab, darab, j;
cin >> N;
for (i = 1; i <= N; i++) {
cin >> Ei >> Ti;
vendegek.push_back(TVendegek(Ei, Ti));
}
max_index = 0;
max_darab = 0;
for (i = 1; i < vendegek.size(); i++) {
darab = 0;
for (j = 0; j < vendegek.size(); j++) {
if (j != i) {
if (vendegek[i].talalkoztak(vendegek[j])) {
darab++;
}
}
}
if (max_darab < darab) {
max_darab = darab;
max_index = i;
}
}
cout << (max_index + 1) << endl;
cout << max_darab << endl;
return 0;
}A probléma pedig az, hogy a feladatnál meg van adva, hogy 0,2 másodperc az időlimit. Kis mennyiségű adatnál szépen le is fut, de ha mondjuk N = több ezer, akkor nem fut le 0,2s alatt...
-
mgoogyi
senior tag
válasz Ron Swanson #4165 üzenetére
Pontos feladatleírás?
for (i = 1; i < vendegek.size(); i++) {
Itt 0-tól kéne indulni, az első vendég is lehet a megoldás.
A TVendegek osztályt átnevezném Vendeg-re, mert az egy darab vendég szerintem.A feltöltésnél add át a vektornak a ctor-ba a méretét, hogy a push_back-nél elkerüld az átméretezést.
Ha kevés benne a hely, újrafoglal magának helyet és másolgat. De várhatóan nem ezen múlik.A kódodnál viszont valszeg a dupla for ciklusnál lehet fogni sokat, az teszi négyzetessé a futási idejét a bemenet méretétől függően. Ez a feladat gyakorlatilag annyi, hogy melyik zárt intervallumnak van a legtöbb metszete a többivel.
Én valami olyasmit csinálnák, hogy rendezném a vendégeket érkezési sorrendben (/távozásiban ) és végigmennék rajtuk lineárisan és jegyezném, hogy most jött valaki, most elment, és azt nézném, hogy mikor voltak a legtöbben.
Oké, most esestt le. Nem kell a vendégeket rendezni, külön az érkezési idejüket egy tömbbe teszed, külön a távozásit és párhuzamosan haladsz a kettőn két külön indexszel. Ha a soron követő két szám között az érkezési <=, akkor növelsz a számlálón, ha meg nem, akkor csökkentesz. Ennek a számlálónak a maximumát keresed és egy vendéget, aki akkor ott volt.
Ez már elég erős tipp szerintem. Lényeg, hogy az egymásba ágyazott ciklusokkal nem fogod tudod megoldani elég gyorsan, csak lineárisan mehetsz végig a vendégek dolgain. -
Drizzt
nagyúr
válasz Ron Swanson #4165 üzenetére
Szerintem itt van az idealis megoldas, a 3 kozul a kozepso. De elkepzelhetonek tartom teljesen mas megkozelitesek is hasonloan gyorsak lehetnek. [link]
A te megoldasod o(n2) - nek nez ki.I am having fun staying poor.
-
dabadab
titán
válasz Ron Swanson #4165 üzenetére
"Kis mennyiségű adatnál szépen le is fut, de ha mondjuk N = több ezer, akkor nem fut le 0,2s alatt... "
Ó, hát erre egyszerű a megoldás, a lista tetejéről válassz valamit: [link]
Komolyabbra fordítva a szót, az a gondod, hogy kb. a vendégek számának négyzetével nő az elvégzendő számítások mennyisége. A megoldás az, ha találsz ennél kisebb ordójú algoritmust. Első blikkre ilyen lehet az, ha a vendégeket nem direktben hasonlítod össze egymással, hanem az időintervallummal machinálsz.
Például csinálsz egy listát, amiben olyan elemek vannak, amik állnak egy időpontból, a már ott lévő vendégek számából és az abban az időpillanatban érkezett vendégek számából és simán ezen a listán mész végig minden egyes vendégre.
Ez egyébként továbbra is algoritmikus kérdés, nem C++ - specifikus.
Hogy ontopic legyek, a C++ kódod valami egészen rettenetes és elavult, szóval fogadni mernék, hogy ezt a magyar (felső)oktatás keretében tanultad , szerintem azt is érdemes jobb átnézni:
1. TVendegek:
Minek az a T? Most komolyan? Mitől lesz bárkinek is jobb attól, hogy az összes osztály neve T-vel kezdődik, mint "type" (sőt, "típus"). Szóval legyen inkább Vendegek.
Miért Vendegek? Egyetlen vendég adatait tárolja, nem többét, szóval legyen inkább Vendeg.
És persze kódot szigorúan angolul írunk, szóval a végleges változat az a Guest.2. erkezes / tavozas
Ha már név: itt pont van értelme annak, hogy jelöljük, hogy ezek adattagok, szóval m_arrive, m_leave
Adattagokat csak kivételes esetben érdemes kirakni publikba, ez meg semmiképpen sem az, szóval legyenek csak private-ok (és a private tagokat érdemes a publicok mögé rakni, mert így jobban olvasható a kód: az elején ott van a mindenkit érdeklő rész, a class API-ja, az implementáció meg elfér hátul).3. TVendegek(const int E, const int T):
A constok itt elég feleslegesek (érték szerit átadott primitívekről van szó), a nevek meg lehetnek nyugodtan beszédesek, a C++-ban a scope-ok miatt az is tök jól működik, hogyC::C(int x) : x(x) {}
De mivel a tagok neve pont az előbb kapott egy m_ előtagot, amúgy se lenne névütközés legyen inkábbGuest(int arrive, int leave)
....
és most mennem kell, majd folytatom, addig a többiek úgyis belekötnek abba, amit írtam
[ Szerkesztve ]
DRM is theft
-
Ron Swanson
senior tag
válasz Ron Swanson #4171 üzenetére
Próbálkozom, de nem sikerül
Vasárnapig meg kéne csinálnom, addig kell beadni. -
mgoogyi
senior tag
válasz Ron Swanson #4172 üzenetére
Melyik része nem sikerül?
A megértés?Amit linkelt Drizzt fórumtárs, az pont ezt oldja meg:
#include<iostream>
#include<algorithm>
using namespace std;
void findMaxGuests(int arrl[], int exit[], int n)
{
// Sort arrival and exit arrays
sort(arrl, arrl+n);
sort(exit, exit+n);
// guests_in indicates number of guests at a time
int guests_in = 1, max_guests = 1, time = arrl[0];
int i = 1, j = 0;
// Similar to merge in merge sort to process
// all events in sorted order
while (i < n && j < n)
{
// If next event in sorted order is arrival,
// increment count of guests
if (arrl[i] <= exit[j])
{
guests_in++;
// Update max_guests if needed
if (guests_in > max_guests)
{
max_guests = guests_in;
time = arrl[i];
}
i++; //increment index of arrival array
}
else // If event is exit, decrement count
{ // of guests.
guests_in--;
j++;
}
}
cout << "Maximum Number of Guests = " << max_guests
<< " at time " << time;
}Az
int arrl[]
az érkezési időpontok tömbje, aint exit[]
pedig a távozási időpontok tömbbje.Ez rendezi le neked ezt a két tömböt gyorsrendezéssel O(N*logN) időben:
sort(arrl, arrl+n);
sort(exit, exit+n);A while ciklus pedig végigmegy a két tömbbön úgy, hogy hol az egyiket lépteti, hol a másikat.
Az"i" az érkezés indexe, a "j" a távozásé.Annyi, hogy ennek a programnak a kimenete az, hogy melyik időpontban voltak a legtöbben és nem az, hogy melyik vendég találkozott a legtöbb másikkal, de a két probléma technikailag szinte azonos.
Ha valami nem világos, kérdezz.
Az eredeti kódoddal a legfőbb baj, hogy volt benne egy egymásba ágyazott for ciklus pár, ami N darab vendég esetén N*N-nel arányos mennyiségű műveletet végez. Ezt hívják O(n^2)-nek és emiatt van az, hogy nagy N-re már túl sok ideig fut a programod. Ugye N=10-nél a a valahány 100 művelet nem gáz, de N=1000-nél már valahány millióról beszélünk. -
mgoogyi
senior tag
válasz Ron Swanson #4174 üzenetére
Rendezésből a buborékrendezést szokták elsőnek tanítani, de az O(n^2)-es, nem leszel vele előrébb.
Ez a sort(...) gyorsrendezést használ, nyugodtan használd.
A feladat megoldását meg nem tanultad órán, azt magadnak kéne kitalálnod, ezzel fejlődsz.
Értsd meg a beszúrt kódot, próbálgasd. Ha azt érted az utolsó betűig, meg tudod majd oldani a saját feladatod is. -
gergoavideki
újonc
Sziasztok!
Codelocks-ban kéne írni egy nagyon alap programot, aki esetleg tudna segíteni és van egy 15 perce dobhatna egy PÜ-t.
Köszi!
-
b.kov
senior tag
válasz gergoavideki #4176 üzenetére
Szia!
Szerintem nyugodtan írhatod ide is a problémádat, több szem többet lát. -
Canela88
újonc
Sziasztok! Remélem tud nekem valaki segíteni, mert már jó ideje kínlódom, és csak nem jön a megvilágosodás. Nemrégen kezdtem C++-t tanulni és megfognak a többdimenziós vectorok. Többek között.
A példa a következő, adott egy vector és szeretném minden 2. elemét kinyerni és összeadni. Tehát az output 30 kell legyen (8+2+16+4).std::vector<std::vector<int>> myVector = {{3, 8, 2},
{2, 5, 16},
{-3, 4, 9}};Köszönöm előre is!
-
Drizzt
nagyúr
válasz Canela88 #4178 üzenetére
Hát iterálj végig az össze elemen sorfolytonosan, lehetőleg index alapján. Előtte csinálj egy int sum = 0 változót, meg egy int position = 0-t. Aztán a beágyazott ciklusban: if (position % 2 == 0) {sum += myVector[j]; position++;} (i a sorokon iteráló int változó, j az oszlopokon.) De c++hoz továbbra is 10+ éve nyúltam, úgyhogy szintaktikailag lehet helytelen.
I am having fun staying poor.
-
Canela88
újonc
Ne haragudj nem értem, hogy honnan tudná, hogy mi a pozíció és nem is jön ki. A vektornak meg kell adjam az i indexét is, mert különben pirosan feszít itt nekem.
Nekem főleg most a megértéssel van a problémám.int sum = 0;
int position = 0;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; ++j) {
if (position % 2 == 0) {
sum += myVector[j];
position++;
}
}
//sum = myVector[0][1] + myVector[1][0] + myVector[1][2] + myVector[2][1];
}ezt írtam. Jó ez így egyáltalán?
-
Drizzt
nagyúr
válasz Canela88 #4180 üzenetére
A pozicio csak egy szamlalo, hogy mennyit leptunk a ciklusban eddig. Minden masodik lepesre akarsz kiirni valamit, ezert kell szamolni, hogy masodik lepesben vagy-e. Es igen, myVector [j] kell. Gondolom a size az 3? Nem kell azt se beegetni, az elso ciklusban lehetne myVector.size() a masodikban myVector[j].size(). Lehet a position neve ha stepsTaken, vagy valami hasonlo lenne, vilagosabb lenne a celja.
Meg latom azt elrontottam, hogy a positiont az if-en kivul kellene leptetni, s a feltetel is position % 2 == 1 lenne helyesen.
I am having fun staying poor.
-
Canela88
újonc
Köszönöm, meg is értettem a stepsTaken lényegét.
int sum = 0;
int stepsTaken = 1;
for (int i = 0; i < myVector.size(); ++i) {
for (int j = 0; j < myVector[j].size(); ++j) {
if (stepsTaken % 2 == 1) {
sum += myVector[j];
}
stepsTaken++;
}
}
std::cout << sum << std::endl;most ez a kód, és nem megy... 29-t ad ki. stepstakent is felvettem 1-re, mert úgy tűnik logikusnak. de mindhiába...sehogy sem akar 30 lenni..
-
Bruce1967
tag
Sziasztok!
Lenne egy olyan kérdésem hogy ki mivel ir programot c++ban én spec code blocksban.
Nekem valahogy a c++ jobban fekszik mint a Java de melyik az erősebb nyelv amivel a legtöbb dologra lehet irni?"Ave"
-
mgoogyi
senior tag
-
dobragab
addikt
válasz Bruce1967 #4185 üzenetére
VS2015 / VS2017 + ReSharper C++. Amúgy amíg a tanulás legelején vagy, addig CodeBlocks-t érdemes, utána CLion-re érdemes áttérni. VS+ReSharper legnagyobb előnye a CLion-höz képest, hogy nagy kódbázison gyorsabb. pl. a "go to definition" meg ilyen dolgok, azt meg úgyse használod ki.
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
cadtamas
tag
Sziasztok.
A tanuljuk meg a c++ nyelvet 24 óra alatt c. könyvből tanulok és az osztályoknál járok.
Van néhány dolog amit nem értek a példafeladatban.
Ez a header. Ez tiszta.#pragma once
# include <iostream>
class Point
{
private:
int itsX;
int itsY;
public:
void setX(int x) { int itsX = x; }
void setY(int y) { int itsY = y; }
int getX() const { return itsX; }
int getY() const { return itsY; }
};
class Rectangle
{
public:
Rectangle(int top, int left, int bottom, int right);
//~Rectangle();
int getRight() const { return itsRight; }
int getLeft() const { return itsLeft; }
int getTop() const { return itsTop; }
int getBottom() const { return itsBottom; }
Point getUpperLeft() const { return itsUpperLeft; }
Point getLowerLeft() const { return itsLowerLeft; }
Point getUpperRight() const { return itsUpperRight; }
Point getLowerRight() const { return itsLowerRight; }
void setUpperLeft(Point location);
void setLowerLeft(Point location);
void setUpperRight(Point location);
void setLowerRight(Point location);
void setRight(int right);
void setLeft(int left);
void setTop(int top);
void setBottom(int bottom);
int getArea() const;
private:
int itsTop;
int itsBottom;
int itsLeft;
int itsRight;
Point itsUpperLeft;
Point itsUpperRight;
Point itsLowerRight;
Point itsLowerLeft;
};Viszont itt több helyen elakadtam:
#include "rect.h"
Rectangle::Rectangle(int top, int left, int bottom, int right) //konstruktor, idáig rendben vagyunk
{
itsTop = top; //Ez elvileg az implementáció, amit nem taglal a könyv, hogy miért kell és később miért nem használjuk semmire.
itsRight = right;
itsLeft = left;
itsBottom = bottom;
itsUpperLeft.setX(left);
itsUpperLeft.setY(top);
itsUpperRight.setX(right);
itsUpperRight.setY(top);
itsLowerLeft.setX(left);
itsLowerLeft.setY(bottom);
itsLowerRight.setX(right);
itsLowerRight.setY(bottom);
}
//ide kellene gondolom a destruktor, ami azért jó, mert memóriát szabadít fel?
void Rectangle::setUpperLeft(Point location) //definiáljuk a függvényt
{
itsUpperLeft = location; //módosítja a változót ami elvileg az egyetlen feladata.
itsUpperRight.setY(location.getY()); //módosítja a JobbFelső pont Y értékét, de miért???
itsLowerLeft.setX(location.getX()); //módosítja a BalAlsó pont X értékét, de miért???
itsTop = location.getY(); //a test felső vonalát határozza meg, de nem ez a dolga!!!
itsLeft = location.getX(); //a test bal szélső vonalát határozza meg, de nem ez a dolga!!!
}
void Rectangle::setLowerLeft(Point location)
{
itsLowerLeft = location;
itsLowerRight.setY(location.getY());
itsUpperLeft.setX(location.getX());
itsBottom = location.getY();
itsLeft = location.getX();
}
void Rectangle::setLowerRight(Point location)
{
itsLowerRight = location;
itsLowerLeft.setY(location.getY());
itsUpperRight.setX(location.getX());
itsBottom = location.getY();
itsRight = location.getX();
}
void Rectangle::setUpperRight(Point location)
{
itsUpperRight = location;
itsUpperLeft.setY(location.getY());
itsLowerRight.setX(location.getX());
itsTop = location.getY();
itsRight = location.getX();
}
void Rectangle::setTop(int top) //beállítja a test felső vonalát. Ugyanazt mint a setUpperLeft() függvény. MIÉRT???
{
itsTop = top; //Ez lenne a dolga
itsUpperLeft.setY(top); //Ez ugyanazt módosítja, mint a setUpperLeft() függvény. (Részben) De ez nem ennek a feladata...
itsUpperRight.setY(top); //Ez ugyanazt módosítja, mint a setUpperRight() függvény. (Részben) De ez nem ennek a feladata...
}
void Rectangle::setLeft(int left)
{
itsLeft = left;
itsUpperLeft.setX(left);
itsLowerLeft.setX(left);
}
void Rectangle::setBottom(int bottom)
{
itsBottom = bottom;
itsLowerLeft.setY(bottom);
itsLowerRight.setY(bottom);
}
void Rectangle::setRight(int right)
{
itsRight = right;
itsUpperRight.setX(right);
itsLowerRight.setX(right);
}
int Rectangle::getArea() const
{
int width = itsRight - itsLeft;
int height = itsTop - itsBottom;
return (width*height);
}
int main()
{
Rectangle MyRectangle(100, 20, 50, 80); //Létrehozzuk a négyszöget
int Area = MyRectangle.getArea();
std::cout << "Terulet: " << Area << "\n";
std::cout << "Bal felso pont x koordinataja: ";
std::cout << MyRectangle.getUpperLeft().getX()<< std::endl; //ennek 20-nak kellene lennie, de nem annyi.
system("pause");
return 0;
}
Kommenteltem, ami nem világos. Tudnátok segíteni, hogy megértsem mi, miért történik? -
mgoogyi
senior tag
válasz cadtamas #4190 üzenetére
//Ez elvileg az implementáció, amit nem taglal a könyv, hogy miért kell és később miért nem használjuk semmire.
-> Az implementáció írja le a dolgok működését, a .h-ban meg azt látod, hogy mit tudsz csinálni majd ezen az osztályon//ide kellene gondolom a destruktor, ami azért jó, mert memóriát szabadít fel?
-> vagy egyéb resource-öket enged el, de az osztályodban nincs ilyen. Akkor fogsz látni destruktort, ha az osztályodban lesz olyan, hogy "new"setupperleft:
//módosítja a JobbFelső pont Y értékét, de miért???
-> azért, mert ez egy téglalap, ha a bal felső sarkát feljebb húzod, a jobb felsőnek is követnie kell//a test felső vonalát határozza meg, de nem ez a dolga!!!
-> dehogynem, az itstop értékét, azaz mi a legnagyobb Y értéke a téglalapnak, módosítani kell, amikor valamelyik sarkát arrébb teszedsetTop(int top):
//beállítja a test felső vonalát. Ugyanazt mint a setUpperLeft() függvény. MIÉRT???
-> azért, mert ez a függvény a téglalap felső oldalát teszi arrébb, amivel együtt mozognak a felső sarkai -
cadtamas
tag
Rectangle::Rectangle(int top, int left, int bottom, int right) //konstruktor, idáig rendben vagyunk
{
itsTop = top; //Ez elvileg az implementáció, amit nem taglal a könyv, hogy miért kell és később miért nem használjuk semmire.
itsRight = right;
itsLeft = left;
itsBottom = bottom;
itsUpperLeft.setX(left);
itsUpperLeft.setY(top);
itsUpperRight.setX(right);
itsUpperRight.setY(top);
itsLowerLeft.setX(left);
itsLowerLeft.setY(bottom);
itsLowerRight.setX(right);
itsLowerRight.setY(bottom);
}Ugye az implementáció azért kell, mert az alapján fog elkészülni a négyszög. Gyakorlatilag automatikusan lefutnak ezek az utasítások, amikor egy négyszög objektumot létrehozunk.
Viszont az első 4 változó privát elérésű tag. Itt mégis lehet nekik közvetlenül értéket adni?
Vagy ez ilyenkor nem számít? Vagy ez a négy változó nem is az a változó amit a .h fájlban deklaráltunk, hanem valami helyi dolog?Elnézést a hülye kérdésekért, de ha ezeket nem rakom tisztába, később tutira nem fogom érteni, hogy mi történik.
-
mgoogyi
senior tag
válasz cadtamas #4193 üzenetére
Az implementáció mondja meg, hogy mit csinálnak a függvények. Anélkül nincs program, csak a függvények fejlécei. Az implementációt találod a cpp fileban.
A .h-ban megmondod, hogy ilyen-olyan függvényeid vannak az osztályban, meg ilye-olyan adattagjaid.
A .cpp-ben meg elvégzed az érdemi munkát, azaz kifejted(implementálod), hogy mit csinál a konstruktor, mit csinál a settop és a többi függvény. Ha ezt nem tennéd meg, a program futásakor nem lenne semmi a függvényhívások mögött.A privát változókat az osztály saját függvényei látják, egyedül előttük nem rejtett. Ha legalább ők nem látnák, akkor semmi értelme nem lenne a privátnak.
Ezek az osztály saját belső állapotát tükroző változók, nem lokálisak. A lokálisnak látnád a deklarációját a függvény elején, pl. int itsTop;
Az osztályra meg úgy gondolj, mint egy olyan valamire, aminek a belső változói adják az állapotát és a függvények pedig azt módosítják vagy azt felhasználva csinálnak valamit.
Amikor a konstruktor lefut, akkor éppen frissen létrejött az osztályodból egy új objektum. A konstruktor a kezdeti állapotát állítja be az objektumodnak. Ezután az objektumon az osztály minden publikus függvényét meghívhatod, ami konkrétan azon az objektumon fog dolgozni. Egy osztályból annyi objektumot csinálsz(példány példányosítasz), amennyit akarsz. Mindegyiknek meglesz a saját belső független állapota, saját itsTop, itsRight stb. belső értékekkel.
[ Szerkesztve ]
-
dobragab
addikt
válasz cadtamas #4190 üzenetére
Most, hogy mar erted is, hadd szidjam kicsit a feladatot.
A legnagyobb problema a Rectangle-ben, hogy redundans adattagok vannak benne. Alapvetoen ez egy olyan teglalapot tarol, aminek az oldalai parhuzamosak a tengelyekkel, tehat kb. ennyi adattagra lenne szukseg:
Point topLeft;
int width;
int height;vagy
Point topLeft;
Point bottomRight;Hiszen ebbol a kettobol ki lehet szamolni az osszes tobbi adatot, egyetlen osszeadassal / kivonassal. Amugy a getter ertelme pont ez, hogy ha valami nem kozvetlenul all rendelkezesre, akkor is ki tudja szamolni / ossze tudja rakni. Ha ennel tobb adatod van, akkor sziszifuszi harc ezt konzisztensen tartani (ertsd: ne legyenek benne egymasnak ellentmondo adatok), ezert 3-5 soros egy setter. Igy kene mondjuk:
Point getLowerLeft() const
{
return Point(topLeft.getX(), bottomRight.getY());
}A masodik baj, hogy tobb setter, pl. a setTopLeft fuggveny szemantikailag ertelmetlen. Egy teglalap bal felso sarkat hogy allitod? Tolod az egesz teglalapot, hogy a merete maradjon meg, vagy megnyujtod, es 2 pontot mozgatsz vele, hogy a jobb also pont maradjon a helyen? Mivel nem egyertelmu, hogy mit csinal, nem szabadna ilyen nevu fuggvenynek lennie. At lehetne nevezni mondjulk pushTopLeft-re vagy dragTopLeft-re, ugy mar egyertelmu, hogy a teglalapot nyujtja, mint PowerPointban a kep atmeretezese.
Altalaban veve pedig a setter rossz omen, azt sugja (haladobbaknak: code smell, tehat nem feltetlenul rossz, csak nagyon nagy valoszinuseggel), hogy valami nem oke a koddal. (haladobbaknak: Single Responsibility Principle-t sert, konkretan ugy, hogy nincs is responsibility.) Itt pl. az, hogy semmit nem csinal az osztalyod, semmivel sem jobb, mint
struct Point { int x; int y; };
A harmadik problema, hogy a Pont-nak kene konstruktor setter helyett.
struct Point
{
int x;
int y;
Point()
{
x = 0;
y = 0;
}
Point(int x, int y)
{
this->x = x;
this->y = y;
}
};Es igy nem kell bele setter sem, mert felul tudod irni az = operatorral, pl.
topLeft = Point(topLeft.x, topLeft.y + 10);
Destruktort megmutatni semmi ertelme, amig nincs eroforraskezeles (tipikusan: dinamikusan foglalt memoria), es a Rectangle osztalyban amugy sem szabad ilyennek lennie (egy teglalap ne kezeljen mar dinamikus adatot, haladobbaknak: ez megint SRP-t sert). De ezt irtak elottem is.
Negyedik: hibas a Point ket settere (ami amugy nem is kene, lasd fent). Igy lenne helyes:
void setX(int x) { itsX = x; }
void setY(int y) { itsY = y; }Igy hirtelen ennyi, ami bokte a csorom. Azert irtam le, mert az OOP-nek (objektumorientalt programozas) jo lenne, ha nem csak a szintaktikai elemeit tanitanak meg, hanem az elveket, ami menten epiteni es alkalmazni illik. Anelkul semmi ertelme az egesznek.
OFF: amugy sajnos nem talaltam olyan konyvet, ahol le vannak ezek irva rendesen, es nem 500+ oldalban. Ha valaki tud ilyet, ne tartsa magaban.
[ Szerkesztve ]
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
dabadab
titán
válasz dobragab #4196 üzenetére
struct Point
{
int x;
int y;
Point()
{
x = 0;
y = 0;
}
Point(int x, int y)
{
this->x = x;
this->y = y;
}
};Sőt:
struct Point
{
int x;
int y;
Point()
{
x = 0;
y = 0;
}
Point(int x, int y):
x(x),
y(y)
{}
};Nyilván ízlés kérdése, de egyrészt nem szeretem az explicit this-ezést, mert az vagy felesleges vagy valami problémás dolgot takar, másrészt meg szerintem ez nagyon szép és intuitív (és - nem mellesleg - teljesen jól működik).
Amúgy meg van olyan kezdőknek szóló könyv, amit úgy meg bírtak írni, hogy a példák vállalhatóak?...
"az OOP-nek (objektumorientalt programozas) jo lenne, ha nem csak a szintaktikai elemeit tanitanak meg, hanem az elveket, ami menten epiteni es alkalmazni illik. Anelkul semmi ertelme az egesznek."
Így van, mert aztán az ember produkciós kódban olyat lát, hogy
pX->m_pY->m_Z = foo;
(és nem egy ilyen sort, hanem több tízezer sornyi kód van ebben a stílusban írva és persze az osztályok összes tagja public (a Lock() / Unlock() is (amik mondjuk eleve azért vannak, mert a RAII sem ért el hozzájuk))
[ Szerkesztve ]
DRM is theft
-
mgoogyi
senior tag
válasz dabadab #4197 üzenetére
Egyetértek veletek, hogy az OOP-t nem tanítják meg rendesen.
Viszont a kérdező srácnak még lehet korai túlzottan ebbe belemenni, egyelőre szerintem ott tart, hogy a nagyon alap dolgok meglegyenek. Amíg egy egyszerű téglalap reprezentációja ennyi magyarázatra szorul, az nekem azt mutatja, hogy nagyon keveset kódolt még.Visszatérve az OOP-re, nekem a láthatóságokkal kapcsolatban zavar pl, hogy mennyire nem tanítják(és nekem sem tanították), hogy mi a valódi haszna annak, hogy semmit sem szabad feleslegesen publicon hagyni.
Annyit tudnak, hogyha valami private, akkor az nem látszik kívülről, de hogy az miért jó, arra már semmi ötletük nincs.
És hát azért nem tanítják, mert jellemzően a gyakorlatvezető sem tudja. -
dobragab
addikt
válasz dabadab #4197 üzenetére
Vagy meg inkabb, ha C++11:
struct Point
{
int x = 0;
int y = 0;
Point() = default;
Point(int x, int y)
x(x),
y(y)
{}
};Csak mivel a kollega nem hasznalt inicializalo listat, ezert nem akartam abba bonyolodni, hogy megmutassam. Es beepitett tipusokra konkretan egyenerteku a ketto. Majd ha nincs default ctor vagy van dinamikus memoriakezeles, akkor kezd ertelme lenni megmutatni.
Amúgy meg van olyan kezdőknek szóló könyv, amit úgy meg bírtak írni, hogy a példák vállalhatóak?...
Nekem van egy kezdemenyezesem, de eleg hatarozottan a BME mernokinfos prog2-re van szabva, es a C ismeretere epit.
(#4198) mgoogyi
Amíg egy egyszerű téglalap reprezentációja ennyi magyarázatra szorul, az nekem azt mutatja, hogy nagyon keveset kódolt még.
Igen, es nem latom ertelmet annak, hogy OOP-t tanuljon ennyire koran, de hat...
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
Ú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!
- Gaming notebook topik
- Mini-ITX
- Robot fűnyírók
- A régi node-okra koncentrál a szankciók miatt Kína
- Politika
- Itt az első kép a 2024-es Nokia 3210-ről
- Telekom mobilszolgáltatások
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Sony MILC fényképezőgépcsalád
- Kerékpárosok, bringások ide!
- További aktív témák...