1 2 3 4 5 6 | #include <cstdio> int main() { printf("%c%c%c\n", 'T', 'V', 'P'); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <iostream> #include <vector> class Master{ protected: unsigned short i; public: Master():i(5){} virtual unsigned short get(){return 9;} }; class Sub:public Master{ public: Sub(){i=8;} unsigned short get(){return i;} }; int main(){ Master *M_ptr; Sub mySub; M_ptr = &mySub; Sub *S_ptr = dynamic_cast<Sub*>(M_ptr); if(S_ptr) // hier werkt het std::cout << "Works\n"; else std::cerr << "FAIL\n"; std::vector<Master> myVec; myVec.push_back(Sub()); Master *vec_ptr = &myVec[0]; Sub *S_ptr2 = dynamic_cast<Sub*>(vec_ptr); if(S_ptr2) // hier faalt het std::cout << "Works\n"; else std::cout << "FAIL\n"; return 0; } |
um, die destructor klopt idd maar er is toch een virtual methode?quote:Op zaterdag 29 januari 2011 00:15 schreef thabit het volgende:
Nog een probleem met je code is dat je de base class niet polymorf hebt gemaakt. Er moet tenminste 1 virtual methode in zitten; het is sowieso raadzaam om de destructor virtual te maken. Dat classes niet automatisch polymorf zijn is overigens ook een designflater.
O ja, overheen gelezen. Maar dan nog moet je geen polymorfisme toepassen op value-typed objecten.quote:Op zaterdag 29 januari 2011 12:18 schreef netolk het volgende:
[..]
um, die destructor klopt idd maar er is toch een virtual methode?
virtual unsigned short get(){return 9;}
1 | mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ext/new_allocator.h:52: error: forming pointer to reference type `Master&' |
Ja, ik heb het zo bedacht:quote:Op zaterdag 29 januari 2011 17:52 schreef thabit het volgende:
Pas wel een beetje op dat je geen pointers naar ongedefinieerde stukken geheugen laat wijzen.
Ja, als er een destructor bestaat zal deze aangeroepen worden. Dit geldt echter alleen als je classes (of base-types) in de vector opslaat. Als je std::vector<X*> gebruikt, zal de X::~X() destructor niet automatisch aangeroepen worden. Daarom wordt het ook als niet netjes gezien om pointers in containers op te slaan.quote:Op zaterdag 29 januari 2011 18:01 schreef netolk het volgende:
nog een vraagje, roept een vector bij destruction ook de destructor van het type aan? dus zegmaar std::vector<int> roept die dan ook ~int() aan?
Gaat tegen het idee van de stl containers in, namelijk dat de container de eigenaar van de data is. Netter zou zijn de pointer in een class te wikkelen. Dit is echter erg afhankelijk van smaak en stijl, en iedereen weet dat daarover prima te twisten valt.quote:Op zaterdag 29 januari 2011 19:19 schreef thabit het volgende:
Niks mis met pointers in containers, mits je duidelijk aan elke new een delete koppelt.
Mensen kiezen vaak voor c++ vanwege de snelheid, niet omdat de taal zo lekker netjes weg te tikken is... Daarvoor zijn veel geschiktere talen (met garbage collector etc)quote:Op zaterdag 29 januari 2011 19:25 schreef GS42 het volgende:
[..]
Gaat tegen het idee van de stl containers in, namelijk dat de container de eigenaar van de data is. Netter zou zijn de pointer in een class te wikkelen. Dit is echter erg afhankelijk van smaak en stijl, en iedereen weet dat daarover prima te twisten valt.
tja ik kan het ook in een matrix / array zetten maar dat is weer gekut als je er data aan toe wilt voegen, dan kan dat wel met classes die dan naar het volgende object wijzen maar waarom zou ik dat doen als ik ook gewoon vector<int*> kan gebruiken? en het dan via een destructor kan laten verwijderenquote:Op zaterdag 29 januari 2011 19:14 schreef GS42 het volgende:
[..]
Ja, als er een destructor bestaat zal deze aangeroepen worden. Dit geldt echter alleen als je classes (of base-types) in de vector opslaat. Als je std::vector<X*> gebruikt, zal de X::~X() destructor niet automatisch aangeroepen worden. Daarom wordt het ook als niet netjes gezien om pointers in containers op te slaan.
Edit: Oh, ik had het bovenstaande antwoord gemist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <iostream> #include <vector> class Temp{ int i; public: Temp(){} ~Temp(){ std::cout << "Destructor\n"; } }; int main(){ std::vector<Temp> myvec; myvec.push_back(Temp()); return 0; } |
1 2 | Destructor Destructor |
Dat is mogelijk en niets om je zorgen over te maken. Bij het kopieren naar de vector is het mogelijk dat er een kopie gemaakt moet worden en dus voor het oude object een destructor aangeroepen wordt. (Sterker nog, aan de code van je kun je zien dat de compiler dit moet doen.) Ook moet een vector zichzelf vaak in geheugen verplaatsen waarbij het kopieen van objecten moet maken en de destructor kan gebruiken, evenals de copy constructor van de klasse (maar dit zou bij 1 object niet moeten gebeuren).quote:Op zaterdag 29 januari 2011 21:05 schreef netolk het volgende:
die ~int() was even een dummie voor de vraag, maar ik heb dus zo'n vector<Player> waar maar 1 player instaat en toch word de destructor 2x aangeroepen...
Bijvoorbeeld in het vorige voorbeeld. Als je de pointer in een klasse wikkelt die de geheugenafhandeling doet, hoef je er op dit moment niet meer aan te denken. Anders moet je voor elke klasse die een vector<int*> gebruikt, een destructor, copy constructor en eventueel een operator=() schrijven, terwijl een vector<IntPointer> dit zelf op zou kunnen lossen. Maar opnieuw: dit heeft veel met persoonlijke stijl te maken.quote:tja ik kan het ook in een matrix / array zetten maar dat is weer gekut als je er data aan toe wilt voegen, dan kan dat wel met classes die dan naar het volgende object wijzen maar waarom zou ik dat doen als ik ook gewoon vector<int*> kan gebruiken? en het dan via een destructor kan laten verwijderen
Omdat er 2 Temp-objecten zijn.quote:Op zaterdag 29 januari 2011 21:10 schreef netolk het volgende:
code bij mijn vorige post
[ code verwijderd ]
output:
[ code verwijderd ]
en als ik de push_back(Temp()) weglaat roept ie de destructor helemaal niet aan, maar waarom word de destructor 2x aangeroepen als er maar 1 object is?
JA, ik zie het nuquote:Op zaterdag 29 januari 2011 21:17 schreef thabit het volgende:
[..]
Omdat er 2 Temp-objecten zijn.. Zie je waarom?
Dit soort dingen zijn niet te voorkomen zeker?quote:Op zaterdag 29 januari 2011 21:20 schreef thabit het volgende:
Juist. Het zoveelste nadeel van value-typed objecten.
Als je per se wilt dat je vector geen pointers bevat (ik lees net dat references niet mogen), dan vrees ik dat dat lastig gaat worden ja.quote:Op zaterdag 29 januari 2011 21:21 schreef netolk het volgende:
[..]
Dit soort dingen zijn niet te voorkomen zeker?
Als je een c++0x-compatible compiler gebruikt, dan moet je dit kunnen voorkomen door met std::move() een r-value-reference mee te geven aan de push_back. Dan wordt er geen kopie gemaakt. De std::vector hoort dit te ondersteunen.quote:Op zaterdag 29 januari 2011 21:21 schreef netolk het volgende:
[..]
Dit soort dingen zijn niet te voorkomen zeker?
Dan moet je misschien ook even kijken naar de unique- en shared-pointer (c++0x): http://www.icce.rug.nl/documents/cplusplus/cplusplus18.html#l286quote:Op zaterdag 29 januari 2011 21:34 schreef netolk het volgende:
dus ik ga het dan nu maar op de "nette" manier doen (GS42 ook weer blij)
1 2 3 4 5 | struct T_sptr{ Temp *_ptr T_sptr(Temp *pointer):_ptr(pointer){} ~T_sptr(){delete _ptr; _ptr=0;} }; |
Waar gaat wat dan precies fout?quote:Op zaterdag 29 januari 2011 21:50 schreef netolk het volgende:
hmm... ik had een simpele struct geschreven
[ code verwijderd ]
alleen hiermee geeft het nog eerder een runtime fout...
Het is ook wat te kort door de bocht voor een pointer class. Als deze struct gekopierd wordt, wordt de _ptr by value gekopierd. Dan wordt het oude object vernietigd. Oftewel: het nieuwe object verwijst naar iets wat niet meer bestaat.quote:Op zaterdag 29 januari 2011 21:50 schreef netolk het volgende:
hmm... ik had een simpele struct geschreven
alleen hiermee geeft het nog eerder een runtime fout...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <iostream> #include <vector> #include <memory> int main() { std::vector< std::unique_ptr<int> > pvect; for (size_t idx = 0; idx < 10; ++idx) pvect.push_back(std::unique_ptr<int>(new int(42))); std::cout << "Adding done." << std::endl; for (size_t idx = 0; idx < 10; ++idx) std::cout << *pvect[idx] << ' '; } |
owja, dan hou ik het zelfde probleem natuurlijkquote:Op zaterdag 29 januari 2011 22:08 schreef GS42 het volgende:
[..]
Het is ook wat te kort door de bocht voor een pointer class. Als deze struct gekopierd wordt, wordt de _ptr by value gekopierd. Dan wordt het oude object vernietigd. Oftewel: het nieuwe object verwijst naar iets wat niet meer bestaat.
Als je een eigen pointer class wilt schrijven, moet je denken aan de copy constructor, destructor, operator= en eventueel de operator* en operator->. Daarom zijn de stl-pointers ook erg handig:
[ code verwijderd ]
Let wel dat je compileert met -std=c++0x.
Sowieso wordt een nieuw object gemaakt, de unique_pointer is namelijk een object. Voor hetgene waar de ptr naar wijst hoeft dit echter niet te gelden. Als het mogelijk is, wordt de move constructor gebruikt waardoor dus geen deep copy nodig is. Dat is hier na te lezen.quote:Op zaterdag 29 januari 2011 22:16 schreef netolk het volgende:
maar die unique pointer die maakt dan dus een nieuw opject aan als het gekopieerd word?
ik gebruik de C++ compiler van mingw (32-bit) maar ik kan nergens vinden of het dat -std=c++0x ondersteund... of hoe ik het aan de compiler moet mee geven, heeft iemand hier ervaring mee?quote:Op zaterdag 29 januari 2011 22:16 schreef GS42 het volgende:
[..]
Sowieso wordt een nieuw object gemaakt, de unique_pointer is namelijk een object. Voor hetgene waar de ptr naar wijst hoeft dit echter niet te gelden. Als het mogelijk is, wordt de move constructor gebruikt waardoor dus geen deep copy nodig is. Dat is hier na te lezen.
Ik verwacht niet dat in een vector kopieen worden gemaakt. Het overzetten naar een linked list hoeft niet moeilijk te zijn, je pakt bijvoorbeeld een list<> container. Maar ik denk niet dat het nodig is in dit geval.
(Het lijkt ondertussen wel alsof ik reclame maak voor de C++ Annotations.)
Als je een nieuwe versie gebruikt van het MinGW pakket, dan wel. Je compiler-versie vind je zo: g++ -vquote:Op zaterdag 29 januari 2011 22:37 schreef netolk het volgende:
ik gebruik de C++ compiler van mingw (32-bit) maar ik kan nergens vinden of het dat -std=c++0x ondersteund... of hoe ik het aan de compiler moet mee geven, heeft iemand hier ervaring mee?
waarvoor is -wall en auto-import importeert dat alle files in de map waar main staat?quote:Op zaterdag 29 januari 2011 22:44 schreef GS42 het volgende:
[..]
Als je een nieuwe versie gebruikt van het MinGW pakket, dan wel. Je compiler-versie vind je zo: g++ -v
En de optie kan je uiteraard op dezelfde manier meegeven. Ik zit op hetzelfde systeem (GCC 4.5.0) en compileer zo: g++ -Wall -std=c++0x -o main -enable-auto-import -O3 main.cc
De -Wall is een redleijk veelvoorkomende optie die alle warnings (Warnings ALL: Wall) aanzet, waardoor je tijdens het compileren melding krijgt van legale maar mogelijk gevaarlijke dingen (zoals statements die niets doen of het vergelijken van signed met unsigned waarden).quote:Op zondag 30 januari 2011 09:37 schreef netolk het volgende:
[..]
waarvoor is -wall en auto-import importeert dat alle files in de map waar main staat?
Ja, het installeren van MinGW gaat bij mij ook (schijnbaar) willekeurig goed of fout. Al het oude eerst verwijderen (of verplaatsen, ik heb c:/mingw en c:/mingw_old) en dan proberen de getting started te volgen. Toen het eenmaal goed gelukt was, heb ik de map 'mingw' gekopieerd zodat ik deze bij een nieuwe installatie gewoon op een computer kan plakken, zodat ik niet dat hele installatieproces door hoef te lopen. Als het je niet lukt, kan ik je misschien mijn installatie-map (~250mb) wel doorspelen.quote:kut, nu mis ik libgmp-10.dll ... terwijl die wel gewoon op mn pc staat...
SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.Verder heb ik ervoor gekozen om zoveel kleine functies te gebruiken, omdat ik het dan makkelijker kan uitbreiden en het overzichtelijker blijft.
Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
quote:Op zondag 30 januari 2011 16:14 schreef Jeroentk het volgende:
Goedemiddag,
Twee dagen geleden ben ik begonnen met het leren van C++. Heb verder eigenlijk geen programmeerervaring, maar het leek me wel interessant. Mijn eerste programma heb ik nu gemaakt en het is enigszins gelukt. Het programma vraagt eerst om hoeveel getallen je bij elkaar wilt optellen, vraagt daarna om de getallen, stopt ze in een array en geeft vervolgens het antwoord. Helaas zit er wel een grote, potentiële error in, en dat is dat wanneer je bij het invoeren van de getallen geen getal invoert. Hierdoor crash hij (natuurlijk), maar ik weet niet hoe ik dmv bijv. een if of do..while die eruit kan vissen. Weten jullie hoe dat moet?
Verder heb ik zojuist geprobeerd om de ingevoerde getallen doubles ipv integers te maken. Dat lukte wel, maar steeds geeft hij op het einde een error. Hij heeft dan al wel de laatste functie uitgevoerd. Ik heb hieronder eerst de add.cpp gepost, en daarna de main.cpp.SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.Kun je iets specifieker zijn in de foutmeldingen etc?SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.Verder heb ik ervoor gekozen om zoveel kleine functies te gebruiken, omdat ik het dan makkelijker kan uitbreiden en het overzichtelijker blijft.
Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
Een std::vector kan handig zijn als je met arrays wilt werken van variabele lengte.
Verder kun je in plaats van met references als argumenten te werken, de berekende waarde ook als uitkomst meegeven dus, bijvoorbeeld, int AantalGetallen() ipv void AantalGetallen(int &nAantal).
Oeh, een excuus om ongegeneerd te gaan muggenziften.quote:Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
1 | for (size_t idx = 0; idx < 10; ++idx) |
1 | void Vraag(double *&pnGetallen, int nAantal) |
1 | double *pnGetallen = new double; |
1 2 | double d = 3.14; double *d_ptr = &d; |
1 2 3 4 5 6 7 8 9 10 11 | #include <iostream> int main() { size_t input; std::cout << "Voer een (positief) getal in: "; if (std::cin >> input) std::cout << "Uw getal is " << input << '\n'; else std::cout << "Verkeerde invoer.\n"; } |
hmm die -wall deed ie hoe dan ook altijd al bij mij, maar krijg die mingw echt niet reïnstalleerd...quote:Op zondag 30 januari 2011 12:31 schreef GS42 het volgende:
[..]
De -Wall is een redleijk veelvoorkomende optie die alle warnings (Warnings ALL: Wall) aanzet, waardoor je tijdens het compileren melding krijgt van legale maar mogelijk gevaarlijke dingen (zoals statements die niets doen of het vergelijken van signed met unsigned waarden).
De enable-auto-import heb ik eigenlijk alleen voor MinGW hoeven gebruiken (en dus niet onder Linux), maar zorgt ervoor dat een waarschuwing over het importeren van dll's niet in beeld komt. Volgens mij is dit Windows- (en misschien zelfs MinGW-) specifiek.
[..]
Ja, het installeren van MinGW gaat bij mij ook (schijnbaar) willekeurig goed of fout. Al het oude eerst verwijderen (of verplaatsen, ik heb c:/mingw en c:/mingw_old) en dan proberen de getting started te volgen. Toen het eenmaal goed gelukt was, heb ik de map 'mingw' gekopieerd zodat ik deze bij een nieuwe installatie gewoon op een computer kan plakken, zodat ik niet dat hele installatieproces door hoef te lopen. Als het je niet lukt, kan ik je misschien mijn installatie-map (~250mb) wel doorspelen.
SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.De error die ik kreeg nadat ik van enkele ints doubles had gemaakt (zodat ik ook 0.66 + 0.33 kon doen etc.):SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.Verder leek het me juist handig om voids te gebruiken, zodat ik geen hele functies in functies hoefde in te voeren? (zoals GeefResultaat(Vraag(AantalGetallen(), AantalGetallen(), Bereken(Vraag(AantalGetallen), AantalGetallen(), ... etc.
bij mij ook niet...quote:
quote:Op zondag 30 januari 2011 17:05 schreef Jeroentk het volgende:
De error wanneer je geen getal invoert:SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.De error die ik kreeg nadat ik van enkele ints doubles had gemaakt (zodat ik ook 0.66 + 0.33 kon doen etc.):Je kan ook iets doen als n = AantalGetallen() ipv Aantalgetallen(n)SPOILEROm spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.Verder leek het me juist handig om voids te gebruiken, zodat ik geen hele functies in functies hoefde in te voeren? (zoals GeefResultaat(Vraag(AantalGetallen(), AantalGetallen(), Bereken(Vraag(AantalGetallen), AantalGetallen(), ... etc.
Forum Opties | |
---|---|
Forumhop: | |
Hop naar: |