[c++] design- en coding-styles

Pagina: 1
Acties:
  • 189 views sinds 30-01-2008
  • Reageer

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik ben aan het overstappen van Windows naar Linux, ben zwaar onder de indruk van Fluxbox nadat ik KDE een onnodig groot vond. Ik ben de sources van Fluxbox wat aan het doorbladeren geweest (en daar kan veel verbeterd worden), dus ben ik mijn c++ kennis weer aan het opfrissen (voor zover dat er ooit goed is geweest). Ik zit op dit moment alleen met 'dubbele' includes.

Ik zie dat ze dat oplossen met een ifndef BLAAT etc etc, maar ik vind dit nogal vrij onhandig. Ze hadden dit veel beter op kunnen lossen door het door de compiler te laten doen, dan door de preprocessor. Is dit dus de standaard manier om van botsende header files af te komen?

Verwijderd

Ja.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
[offtopic]
Kan je ook stacktraces of iets in die geest krijgen? Een segmentationfault vind ik niet bepaald lief

ik gebruik trouwens g++

Verwijderd

Ja, onder andere door je programma in een debugger te draaien (zoals die van C++ Builder of Visual C++).

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Mijn c(++) kennis is behoorlijk klein, maar toch ff iets zeggen:
Bij mijn weten moet je elke gebruikte externe functie in je c file gedeclareerd hebben (d.m.v. een geinclude header-file meestal). De volgende situatie zou dus niet mogen als je geen botsende headers wil:
tools.c gebruikt een functie uit files.c
main.c gebruikt een functie uit tools.c en files.c

Alleen door een extreem gelaagd ontwerp zou je het voorkomen en dat krijg je niet voor elkaar. Leg je neer bij de ifndef structuur denk ik zo :)

Stacktraces kun je m.b.v. gdb krijgen, daar is vast genoeg over te vinden op internet.

|_____vakje______|


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 27 oktober 2002 @ 21:30:
Ja, onder andere door je programma in een debugger te draaien (zoals die van C++ Builder of Visual C++).


gdb dus in het geval van Alarmnummer :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
[edit]
loopt uit zijn nek te lullen.

Verwijderd

Alarmnummer schreef op 27 oktober 2002 @ 21:11:
[offtopic]
Kan je ook stacktraces of iets in die geest krijgen? Een segmentationfault vind ik niet bepaald lief

ik gebruik trouwens g++
stacktraces:
man catchsegv

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
back on topic:
GCC herkent de #ifndef - #define - #endif header guard constructie, en cached
deze file dan. (Wat MSVC met #pragma once doet, maar dan in standaard C++)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Maar wat ik hieruit opmaak is dat dit dus de standaard is. Hoe zit het trouwens met de naamgeving? Ik zie veel cc en hh bestanden, maar het is toch cpp en h? En wat zijn trouwens de aanroep kosten van een methode die een implementatie is van een pure virtuele methode..

dus:
code:
1
2
3
4
5
6
7
8
9
10
11
12
class A{
public:
   virtual void foo() = 0;
};

class B: public A{
public:
   void foo(){}
};

A* x = new B();
x->foo()

Dit hoeft niet dynamisch uitgezocht te worden, en de java compiler die is gelukkig zo intelligent dat statisch uitgezocht wordt welke methode er aangeroepen gaat worden (tenslotte kan er maar 1 worden aangeroepen). Maar hoe zit dit bij c++? (het gaat dus puur om pure virtuele methoden).

[edit]
kromme zinnen er uithalen.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

[nohtml]
Alarmnummer:
Maar wat ik hieruit opmaak is dat dit dus de standaard is. Hoe zit het trouwens met de naamgeving? Ik zie veel cc en hh bestanden, maar het is toch cpp en h?
Ja, ook hpp wordt zelfs nog wel eens gebruikt. Voor zover ik weet, wordt er in de gnu sferen meestal de eerste variant (cc, hh) gebruikt voor resp. C++ source- en headerfiles, en .c en .h voor de C source- en headerfiles.

Binnen Windows en DOS-sferen kom je idd meer de .CPP en .H(PP) extensies tegen voor C++ bestanden

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
En wat is trouwens de standaard met destructors? Ik heb absoluut geen problemen met de destructors, afgezien van het feit dat je meerdere keren een destructor op een object zou kunnen aanroepen. Dit zou je op kunnen lossen door een destructed flag te gaan gebruiken, is dit ook een standaard? Of is er iets beters?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
drm schreef op 28 oktober 2002 @ 12:32:
[nohtml]
[...]

Ja, ook hpp wordt zelfs nog wel eens gebruikt. Voor zover ik weet, wordt er in de gnu sferen meestal de eerste variant (cc, hh) gebruikt voor resp. C++ source- en headerfiles, en .c en .h voor de C source- en headerfiles.

Binnen Windows en DOS-sferen kom je idd meer de .CPP en .H(PP) extensies tegen voor C++ bestanden
Ik gebruikte al cc en hh B) En verder wil ik zoveel mogelijk de standaard gebruiken, dus cc en hh it`s gona be :)

Verwijderd

Alarmnummer schreef op 28 oktober 2002 @ 12:13:
Dit hoeft niet dynamisch uitgezocht te worden, en de java compiler die is gelukkig zo intelligent dat statisch uitgezocht wordt welke methode er aangeroepen gaat worden (tenslotte kan er maar 1 worden aangeroepen). Maar hoe zit dit bij c++? (het gaat dus puur om pure virtuele methoden).
C++ is hier minimaal net zo slim als java. ;) Als het type van een object in compile-time bekend is, dan zal de compiler een virtual method als een gewonen method aanroepen (dus zonder lookup in de vtable).
Alarmnummer schreef op 28 oktober 2002 @ 12:33:
En wat is trouwens de standaard met destructors? Ik heb absoluut geen problemen met de destructors, afgezien van het feit dat je meerdere keren een destructor op een object zou kunnen aanroepen. Dit zou je op kunnen lossen door een destructed flag te gaan gebruiken, is dit ook een standaard? Of is er iets beters?
Het is de bedoeling ervoor te zorgen dat je destructors maar 1x aanroept. Meerdere malen een object destroyen dat maar 1x constructed is, is gewoon een logic error in je programma.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Alarmnummer:
En wat is trouwens de standaard met destructors? Ik heb absoluut geen problemen met de destructors, afgezien van het feit dat je meerdere keren een destructor op een object zou kunnen aanroepen. Dit zou je op kunnen lossen door een destructed flag te gaan gebruiken, is dit ook een standaard? Of is er iets beters?

Wanneer je een object delete, de pointer(s) op NULL zetten, zodat je er niet meer bij kan. Verder de destructor niet aanroepen.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Verwijderd schreef op 28 oktober 2002 @ 13:08:
C++ is hier minimaal net zo slim als java. ;) Als het type van een object in compile-time bekend is, dan zal de compiler een virtual method als een gewonen method aanroepen (dus zonder lookup in de vtable).
thanx, ik kon het namelijk nergens in mijn c++ boek vinden en het leek me eigelijk wel vrij voor de hand liggend dat de c++ compiler dit wel kon optimaliseren.
Het is de bedoeling ervoor te zorgen dat je destructors maar 1x aanroept. Meerdere malen een object destroyen dat maar 1x constructed is, is gewoon een logic error in je programma.
vb van hoe het fout kan gaan:

Land* nederland = new Land("nederland"):
Persoon* peter = new Persoon("peter",nederland);
Persoon* jan = new Persoon("jan",nederland);
Dit soort situaties komen veel voor, wie is dan verantwoordelijk voor het opruimen van het object nederland?

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

degene die 'm gecreeerd heeft :) Redelijk eenvoudige stelregel.

edit:
Hoewel ik me heel goed voor kan stellen dat dat lang niet altijd opgaat :X

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Als je geen speciale code daaromtrend gegeven hebt is dat degene die nederland aangemaakt heeft.

Of je moet een owner princiepe inbouwen hier, maar dat lijkt me in dit geval niet gewenst.

We adore chaos because we like to restore order - M.C. Escher


  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

drm schreef op 28 oktober 2002 @ 13:20:
degene die 'm gecreeerd heeft :) Redelijk eenvoudige stelregel.

edit:
Hoewel ik me heel goed voor kan stellen dat dat lang niet altijd opgaat :X
In die gevallen waar 't niet opgaat wordt "de laatste die het gebouw verlaat geacht het licht uit te doen". (Maar dat levert een hoop gedoe op, zo moet je natuurlijk wel weten of je nog als enige over bent).

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Dat krijg je van all die garbage collection, programmeurs weten niet mee wanneer objecten vrijgemaakt horen/kunnen worden. ;)

Of het echt een gemis wordt denk ik niet, maar degene die het nog wel kunnen, kunnen daarover mooi praten later: 'weet je nog vroeger? toen had je nog geen garbage collection en wist je nog echt wanneer een object gedestroyed werd' :p

We adore chaos because we like to restore order - M.C. Escher


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Alarmnummer schreef op 28 oktober 2002 @ 13:19:
vb van hoe het fout kan gaan:

Land* nederland = new Land("nederland"):
Persoon* peter = new Persoon("peter",nederland);
Persoon* jan = new Persoon("jan",nederland);
Dit soort situaties komen veel voor, wie is dan verantwoordelijk voor het opruimen van het object nederland?
Smart pointers met reference counts doen wonderen als je dit in een keer goed wil oplossen.

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

LordLarry schreef op 28 oktober 2002 @ 13:25:
Dat krijg je van all die garbage collection, programmeurs weten niet mee wanneer objecten vrijgemaakt horen/kunnen worden. ;)

Of het echt een gemis wordt denk ik niet, maar degene die het nog wel kunnen, kunnen daarover mooi praten later: 'weet je nog vroeger? toen had je nog geen garbage collection en wist je nog echt wanneer een object gedestroyed werd' :p
Ik citeer de sig van MSalters: If there is no garbage in a language you don't have to collect it.

Garbage collectors zijn EEEVIL. De single most useful thing van een goeie class, namelijk de destructor, wordt er nutteloos door omdat je geen idee hebt wanneer het ding wordt aangeroepen.

Gelukkig kun je het kreng in C# naar het schijnt uitzetten met System.Gc.Disable() of zoiets.

Professionele website nodig?


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Ben het helemaal met je eens.

IDisposable implementeren en dan kan het wel in .Net

We adore chaos because we like to restore order - M.C. Escher


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
curry684 schreef op 28 oktober 2002 @ 13:27:
[...]

Smart pointers met reference counts doen wonderen als je dit in een keer goed wil oplossen.
En is dit onderdeel van g++?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alarmnummer schreef op 28 oktober 2002 @ 14:15:
[...]

En is dit onderdeel van g++?


auto_ptr is onderdeel van de STL idd, maar dat is meer om gealloceerde objecten die buiten scope gaan te verwijderen
Er zijn ook populaire C++ libs te vinden die een smartpointer implementatie hebben (zie bijvoorbeeld boost)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Je kunt het eenvoudig zelf implementeren (met templates). Het is geen onderdeel van de STL omdat reference counting geen generieke oplossing is (deadlocks op circular references).

Overigens is het de bedoeling van C++ & STL om zo min mogelijk zelf op de heap te gaan zitten prutsen met new en delete. Als het enigzins mogelijk is kun je beter objecten op de stack of in een container aanmaken, dan wordt er automatisch goed opgeruimd (bij het uit scope gaan van de container/het object).
C++:
1
2
3
4
5
std::vector<Land> landen;
landen.push_back(Land("nederland"));
std::vector<Persoon> personen;
personen.push_back(Persoon("peter", &landen.back()));
personen.push_back(Persoon("jan", &landen.back()));

[ Voor 0% gewijzigd door Verwijderd op 28-10-2002 14:39 . Reden: te snel voorbeeldcode getiept ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Wat is trouwens de de gebruikelijke naamgeving voor include 'defines'?

Ik gebruik nu dit voor Persoon.hh
code:
1
2
3
4
5
6
7
8
#ifndef Persoon_h
#define Persoon_h

class Persoon{
public:
   Persoon();
};
#endif

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Alarmnummer:
Wat is trouwens de de gebruikelijke naamgeving voor include 'defines'?

Ik gebruik nu dit voor Persoon.hh
code:
1
2
3
4
5
6
7
8
#ifndef Persoon_h
#define Persoon_h

class Persoon{
public:
   Persoon();
};
#endif


Meestal wordt gewoon de naam van het bestand gebruikt, met de punten vervangen door underscores. Dus in jouw geval zou het Persoon_hh worden.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Verwijderd

Alarmnummer schreef op 28 oktober 2002 @ 15:54:
Wat is trouwens de de gebruikelijke naamgeving voor include 'defines'?
Zowieso is het gebruik van uppercase voor preprocessor macro's gebruikelijk. Verder gebruik ik meestal gewoon de de volledige naam vanuit de global scope van de class of namespace waar de header van is, maar dan dus in caps en met _ in plaats van ::. Een _H extensie vind ik overbodig.

Verwijderd

Gebruikelijke conventie: 2 underscores, gevolgd door de filenaam in hoofdletters, met leestekens vervangen door underscores. dus: #ifndef __PERSOON_HH

Verwijderd

drm schreef op 28 oktober 2002 @ 15:56:
Meestal wordt gewoon de naam van het bestand gebruikt, met de punten vervangen door underscores. Dus in jouw geval zou het Persoon_hh worden.
Dit is volgens mij een onhandige conventie (die dan ook niet vaak gebruikt wordt). Als je namelijk bijvoorbeeld meedere utilities.h in verschillende directories (met inhoud in verschillende namespaces) hebt die allebei UTILITIES_H gebruiken, kan dat een probleem worden als een bepaalde translation unit allebei de utilities.h files include't. Het opnemen van het hele 'path' naar de namespace of class naam in de header guard macro is beter (en gebruikelijker) omdat dat gegarandeerd uniek is in een programma.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Alarmnummer schreef op 28 oktober 2002 @ 13:19:
[...]
vb van hoe het fout kan gaan:

Land* nederland = new Land("nederland"):
Persoon* peter = new Persoon("peter",nederland);
Persoon* jan = new Persoon("jan",nederland);
Dit soort situaties komen veel voor, wie is dan verantwoordelijk voor het opruimen van het object nederland?
De destructor van het object, waarvan nederland een member is natuurlijk.

Overigens is het onverstandig om meer dan een kale resource (file handle, new'ed pointer, etc. ) in een class te mikken. Als er dan een std::bad_alloc exception komt weet je niet welke pointers je moet deleten/files moet closen. Een auto_ptr<Land> ipv een Land* lost dat op - bij een exceptie wordt de gealloceerde 'Land' voor je gedelete.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Sneechy:
Dit is volgens mij een onhandige conventie (die dan ook niet vaak gebruikt wordt). Als je namelijk bijvoorbeeld meedere utilities.h in verschillende directories (met inhoud in verschillende namespaces) hebt die allebei UTILITIES_H gebruiken, kan dat een probleem worden als een bepaalde translation unit allebei de utilities.h files include't. Het opnemen van het hele 'path' naar de namespace of class naam in de header guard macro is beter (en gebruikelijker) omdat dat gegarandeerd uniek is in een programma.

Daar zat ik idd ook al aan te denken ja :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
En wat zijn verder de conventies van de lokaties van de onderdelen van een class. Dus methodes, constructors/destructors members, statische methodes/members. En ik neem aan dat er ook ingedeeld wordt op access modifier.

Verwijderd

Alarmnummer schreef op 28 oktober 2002 @ 16:23:
En wat zijn verder de conventies van de lokaties van de onderdelen van een class. Dus methodes, constructors/destructors members, statische methodes/members. En ik neem aan dat er ook ingedeeld wordt op access modifier.
Misschien wordt het eens tijd om te kijken naar wat C++ style guides :).

Vergeet trouwens niet dat de volgorde van members (en base classes) in een class definitie bepaalt in welke volgorde die members worden geconstruct (dus soms kun je niet simpelweg indelen op access).

Tot slot wil ik erbij zeggen dat die style guides absoluut niet heilig zijn (ze spreken elkaar zowieso vaak tegen). Het is zeker goed om er eens naar te kijken, maar als je zelf liever een paar andere conventies gebruikt: ga je gang. Het belangrijkste is zoals altijd dat je consistent blijft.

[ Voor 0% gewijzigd door Verwijderd op 28-10-2002 16:31 . Reden: neus.. ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Aha.. handig :)

  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Ik doe altijd gewoon __PROGNAAM_FILENAAM_H :|

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Dan krijg je onnodige collisions. Je kan beter de namespaces er ook voorzetten. Op die manier kan je garanderen dat je nooit een botsing krijgt.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Wat zijn trouwens 'de' links voor standaard c++? Dus oa een beschrijving van de api`s.

Verwijderd

Alarmnummer schreef op 28 oktober 2002 @ 16:57:
Wat zijn trouwens 'de' links voor standaard c++? Dus oa een beschrijving van de api`s.
Ik gebruik:
- Dinkum C++ Library Reference
- SGI STL Reference

Dit zijn overigens slechts droge references. Het is verstandig om een goed boek te kopen over de STL, iostreams, etc, om meer vertrouwd te raken met de achterliggende filosofiën en design decisions/goals.

Verder wordt de C++ Standard Library niet API genoemd (onder andere omdat niet alleen application programmers 'em gebruiken :)).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik heb zelf "Het C++ boek". Ondanks de zielige naam, is het toch een heel aardig boek, waarin je oo`er zeer eenvoudig je weg kan vinden en waar enorm veel C++ specifieke dingen worden behandeld. Ik heb het boek gekocht (een hele tijd geleden toen ik nog niet op GoT kwam en ook geen advies kreeg), maar het is een zeer geslaagde koop geweest :) (in tegenstelling tot sommige andere boeken die eigelijk niets anders zijn dan boekenkast vulsel) :P

Verwijderd

Alarmnummer schreef op 28 oktober 2002 @ 17:17:
Ik heb zelf "Het C++ boek". Ondanks de zielige naam, is het toch een heel aardig boek, waarin je oo`er zeer eenvoudig je weg kan vinden en waar enorm veel C++ specifieke dingen worden behandeld. Ik heb het boek gekocht (een hele tijd geleden toen ik nog niet op GoT kwam en ook geen advies kreeg), maar het is een zeer geslaagde koop geweest :) (in tegenstelling tot sommige andere boeken die eigelijk niets anders zijn dan boekenkast vulsel) :P
The C++ Programming Language gaat vooral over de taal, en verteld maar (relatief) weinig over de standard library. Daarom zat ik meer te denken aan boeken als The C++ Standard Library van Nicolai Josuttis en Standard C++ IOStreams and Locales van Klaus Kreft en Angelika Lange.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

titel maar even gewijzigd, deze dekt de inhoud beter :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
.oisyn schreef op 28 oktober 2002 @ 17:36:
titel maar even gewijzigd, deze dekt de inhoud beter :)
Ik zat al te denken, waar is dat topic van vanmiddag gebleven :)

Back on topic: header guards met dubbele underscores erin (op een willekurige plaats ) zijn voor de compiler; die mag best zelf __HEADER_H_INCLUDED definieren als 'ie een #include "header.h"tegenkomt. Dan doet je eigen #ifndef __HEADER_H_INCLUDED het dus niet meer. ^_[A-Z].* is overigens ook gereserveerd.
^_[A-Z].* is dus een regex, geen perl of een misluke smiley

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Alarmnummer schreef op 28 oktober 2002 @ 15:54:
Wat is trouwens de de gebruikelijke naamgeving voor include 'defines'?
Daar is geen gebruikelijke conventie voor zoals je al gemerkt hebt :)

Ikzelf plaats altijd de sublib en/of namespace-afkorting in de filenaam (en gebruik altijd *.hpp overigens voor C++ headers) en houd dan voor de define dezelfde naam met een trailing capital H, dus de Utilities sectie van de Abc-library wordt bij mij gedeclareerd in AbcUtilities.hpp met als definenaam AbcUtilitiesH. Redelijk minieme kans op naming conflicten :)

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 28 oktober 2002 @ 14:34:
Je kunt het eenvoudig zelf implementeren (met templates). Het is geen onderdeel van de STL omdat reference counting geen generieke oplossing is (deadlocks op circular references).
Vandaar dat je met circulaire relaties altijd een master-slave verband moet leggen door de ene class een smart pointer te geven en de andere een non-reference counting variant daarop: de 'protected' pointer. Deze kun je makkelijk in dezelfde class implementeren overigens.
Overigens is het de bedoeling van C++ & STL om zo min mogelijk zelf op de heap te gaan zitten prutsen met new en delete. Als het enigzins mogelijk is kun je beter objecten op de stack of in een container aanmaken, dan wordt er automatisch goed opgeruimd (bij het uit scope gaan van de container/het object).
En daarom maak je smart pointers altijd op de stack zodat je heap objects automatisch gedereferenced en eventueel opgeruimd worden bij het uit scope gaan van de laatste smart pointer :)

* curry684 snapt waarschijnlijk gewoon niet waarom je dit toevoegt, je ontkomt niet aan heap objects, en juist daarom bestaan er concepten als smart pointers.

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Alarmnummer schreef op 28 oktober 2002 @ 16:47:
Dan krijg je onnodige collisions. Je kan beter de namespaces er ook voorzetten. Op die manier kan je garanderen dat je nooit een botsing krijgt.
Dat kun je nooit garanderen. Als 2 libs toevallig allebei de namespace ::WHIUHUWIHFE gebruiken en daarin een class GYFTTRUPOIPOUHUIFU declareren gaat het nog steeds fout, en dan loopt je include-define hier ook nog fout als ze in een andere header gedefinieerd zijn.

Je kunt alleen je best doen het te voorkomen, en dat is door zoveel mogelijk an sich unieke elementen van de header te combineren. Ik volsta door mijn coding style met lib/namespace prefix en functional-group-suffix volledig, en kan redelijkerwijs ervan uit gaan dat dit nooit zal conflicteren. Garanderen kun je echter echt nooit O-)

Professionele website nodig?


Verwijderd

MSalters schreef op 28 oktober 2002 @ 20:08:
Back on topic: header guards met dubbele underscores erin (op een willekurige plaats ) zijn voor de compiler; die mag best zelf __HEADER_H_INCLUDED definieren als 'ie een #include "header.h"tegenkomt. Dan doet je eigen #ifndef __HEADER_H_INCLUDED het dus niet meer. ^_[A-Z].* is overigens ook gereserveerd.
^_[A-Z].* is dus een regex, geen perl of een misluke smiley
Hmm, mijn specs zeggen dat guards die beginnen en eindigen met dubbele underscores reserved zijn, en guards die beginnen met een enkele underscore.
curry684 schreef op 28 oktober 2002 @ 22:11:
En daarom maak je smart pointers altijd op de stack zodat je heap objects automatisch gedereferenced en eventueel opgeruimd worden bij het uit scope gaan van de laatste smart pointer :)

* curry684 snapt waarschijnlijk gewoon niet waarom je dit toevoegt, je ontkomt niet aan heap objects, en juist daarom bestaan er concepten als smart pointers.
Ik voeg dit toe omdat er veel te veel expliciet op de heap geklooid wordt, vooral door java-programmeurs die overstappen op of een excursietje maken naar c++. Natuurlijk heb je de heap nodig, maar het is beter dit zoveel mogelijk impliciet door de STL te laten regelen. De code hierboven is een goed voorbeeld, waarom objecten op de heap zetten als ze klein en monadisch zijn (maar één Land en Persoon type)?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Overigens kun je best polymorfe objecten op de stack zetten:
code:
1
Base const& polymorph = (rand%2) ? Derived1() : Derived2() ;

dus zelfs daar heb je de heap niet voor nodig.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21:25
(jarig!)
MSalters schreef op 29 oktober 2002 @ 12:35:
Overigens kun je best polymorfe objecten op de stack zetten:
code:
1
Base const& polymorph = (rand%2) ? Derived1() : Derived2() ;

dus zelfs daar heb je de heap niet voor nodig.
Correct me if I'm wrong, maar volgens mij staat je reference nu op de stack. Het tijdelijke object waar die reference naar verwijst zal best ook wel op de stack gezet kunnen worden door de compiler, maar het zou me niets verbazen als dit implementatiespecifiek is.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

MSalters schreef op 29 oktober 2002 @ 12:35:
Overigens kun je best polymorfe objecten op de stack zetten:
code:
1
Base const& polymorph = (rand%2) ? Derived1() : Derived2() ;

dus zelfs daar heb je de heap niet voor nodig.
En dan nu zonder heap de volgende functie implementeren:
C++:
1
Base* CreateRandomDerivedClass();

:z

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Stel dat ik vroegtijdig uit mijn programma spring, zonder dat ik al het geheugen heb vrijgegeven. Wordt dit automatisch vrijgegeven, of heb je dan een klein probleem? Ik neem aan dat ieder programma in zijn eigen space draait, dus je kan ook zien wel geheugen daarbij hoort en eventueel vrijgeven wat nog niet is vrijgegeven.

[edit]
tot nu toe ben ik eigelijk best wel gecharmeerd van c++ Het biedt je de mogelijkheid om echt iets voor een os te schrijven (ik wil dus met die window manager stoeien) en daarnaast hebben macro`s en operator overloading mijn interesse (ik wil zeker nog wat met macro`s gaan doen omdat ik dit niet in andere talen heb kunnen doen).

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34
Alarmnummer schreef op 29 oktober 2002 @ 21:17:
Stel dat ik vroegtijdig uit mijn programma spring, zonder dat ik al het geheugen heb vrijgegeven. Wordt dit automatisch vrijgegeven, of heb je dan een klein probleem? Ik neem aan dat ieder programma in zijn eigen space draait, dus je kan ook zien wel geheugen daarbij hoort en eventueel vrijgeven wat nog niet is vrijgegeven.
Ik geloof dat je dan een probleem hebt. Volgens mij wordt het geheugen niet vrijgegeven en heb je dan dus een memory leak.
tot nu toe ben ik eigelijk best wel gecharmeerd van c++ Het biedt je de mogelijkheid om echt iets voor een os te schrijven (ik wil dus met die window manager stoeien) en daarnaast hebben macro`s en operator overloading mijn interesse (ik wil zeker nog wat met macro`s gaan doen omdat ik dit niet in andere talen heb kunnen doen).

Hmmm... macro's, imho is dat eerder een C - iets, en niet echt C++. Is een macro niet te vergelijken met een inline function?

https://fgheysels.github.io/


  • pjonk
  • Registratie: November 2000
  • Laatst online: 29-12-2025
macro's worden volgens mij vooral gebruikt voor kleine functies. Het is soms sneller om een macro te gebruiken ipv een functie omdat de stack niet gebruikt hoeft te worden wat een kleine performance winst kan opleveren, maar dit merkt je pas als het stukje macro code in een lus wordt gebruikt.

It’s nice to be important but it’s more important to be nice


  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34
JonkieXL schreef op 29 oktober 2002 @ 21:28:
macro's worden volgens mij vooral gebruikt voor kleine functies. Het is soms sneller om een macro te gebruiken ipv een functie omdat de stack niet gebruikt hoeft te worden wat een kleine performance winst kan opleveren, maar dit merkt je pas als het stukje macro code in een lus wordt gebruikt.


AFAIK is dit net hetzelfde als een inline function. Bij het compileren wordt de function call vervangen door de functie-code, zodat er ook niet moet versprongen worden.

https://fgheysels.github.io/


Verwijderd

Nope, je hebt geen probleem. De hele procesruimte wordt vrijgegeven bij het beeindigen van een proces. Memory leaks onstaan als een lopend programma steeds opnieuw geheugen alloceert en dat vervolgens niet vrijgeeft. Beeindig je het lekkende programma dan moet alle heapgeheugen weer vrijkomen.

Testje op een linux-bak:

destheap.cc (lekt 10mb geheugen)
C++:
1
2
3
4
5
int main()
{
    char *leak= new char[10485760]; // 10mb
    return 0;
}


Resultaat:
code:
1
2
3
4
5
6
7
8
9
10
[mietje@boaz prog]$ g++ -o destheap destheap.cc 
[mietje@boaz prog]$ free; ./destheap; free
             total       used       free     shared    buffers     cached
Mem:        255512     209352      46160       2036      32420      67552
-/+ buffers/cache:     109380     146132
Swap:       522104          0     522104
             total       used       free     shared    buffers     cached
Mem:        255512     209352      46160       2036      32420      67552
-/+ buffers/cache:     109380     146132
Swap:       522104          0     522104

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op 29 oktober 2002 @ 21:24:

Hmmm... macro's, imho is dat eerder een C - iets, en niet echt C++. Is een macro niet te vergelijken met een <font="courier new">inline function</font>?


macro's zijn in C++ wat functies en constanten betreft vrij nutteloos, maar: het is enorm handig voor conditional code

Zoals bijvoorbeeld assertions, of gewoon dingen die meegecompileerd moeten worden aan de hand van een bepaalde preprocessor macro (_DEBUG wordt vaak gebruikt):

C++:
1
2
3
4
5
6
void eenFunctie ()
{
#ifdef _DEBUG
    debugOutput ("eenFunctie ()");
#endif
}


hoewel dit natuurlijk veel mooier te schrijven is:

C++:
1
2
3
4
5
6
7
8
9
10
#ifdef _DEBUG
#define OUTPUT(x)    debugOutput (x)
#else
#define OUTPUT(x)
#endif

void eenFunctie ()
{
    OUTPUT ("eenFunctie ()");
}
Verwijderd schreef op 29 oktober 2002 @ 21:39:
Nope, je hebt geen probleem. De hele procesruimte wordt vrijgegeven bij het beeindigen van een proces. Memory leaks onstaan als een lopend programma steeds opnieuw geheugen alloceert en dat vervolgens niet vrijgeeft. Beeindig je het lekkende programma dan moet alle heapgeheugen weer vrijkomen.
klopt idd, maar sommige klassen kunnen rekenen op een aanroep van een destructor (bijvoorbeeld een stream flushen, een temp file deleten, of iets dergelijks). Daarom, en natuurlijk gewoon voor the sake of netheid, is het dus verstandig om wel alles vrij te geven

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 29 oktober 2002 @ 21:39:
Nope, je hebt geen probleem. De hele procesruimte wordt vrijgegeven bij het beeindigen van een proces. Memory leaks onstaan als een lopend programma steeds opnieuw geheugen alloceert en dat vervolgens niet vrijgeeft. Beeindig je het lekkende programma dan moet alle heapgeheugen weer vrijkomen.
Niet helemaal correct als antwoord op de vraag. Idd wordt de hele procesruimte vrijgegeven en kun je dus als proces in principe geen problemen krijgen tenzij je jezelf opblaast. Er zijn echter legio andere manieren om C++ programma's te schrijven dan alleen als stand-alone processen: denk aan DLL's en OCX'en onder Windows, en Linux/Unix kent vast en zeker vergelijkbare mogelijkheden. OCX'en oftewel ActiveX controls zijn in principe ook DLL's, en worden op die manier binnen de process-space van de host uitgevoerd, en bijvoorbeeld IE knalt met lomp geweld totaal uit mekaar als een client-ActiveX maar 1 luttele byte vergeet vrij te geven... ik spreek jammer genoeg uit ervaring :z

Ergo je kunt maar beter goed aanleren alles vrij te geven :)

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik ben al met counting smartpointers bezig (althans lezen) om het grootste gedeelte van de problemen op te lossen mbt geheugen vrijgeven. Ik was al bang dat ik mijn algoritmes moest verneuken omwille van altijd destructors aanroepen, maar laat de stackframes dat maar fijn uitzoeken :D

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Over macro's:
whoami schreef op 29 oktober 2002 @ 21:35:
AFAIK is dit net hetzelfde als een inline function. Bij het compileren wordt de function call vervangen door de functie-code, zodat er ook niet moet versprongen worden.
Tot op zekere hoogte heb je gelijk, maar met macro's kun je veel machtiger dingen doen: token-pasting! Hier en daar errug handig :)

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Alarmnummer schreef op 29 oktober 2002 @ 22:58:
Ik ben al met counting smartpointers bezig (althans lezen) om het grootste gedeelte van de problemen op te lossen mbt geheugen vrijgeven. Ik was al bang dat ik mijn algoritmes moest verneuken omwille van altijd destructors aanroepen, maar laat de stackframes dat maar fijn uitzoeken :D
Once you get used to them you never want to live without them ;)

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zat de denken in termen van code generatie >:) Ik ben in java al bezig geweest met een krachtig mvc framework, en dat wil ik ook binnen c++ gaan toepassen. Het enigste nadeel aan is de syntax. Misschien dat ik met operator overloading wat kan doen, misschien dat ik het met macro`s ga doen. Het gaat trouwens niet zozeer om een praktisch nut van de aanpak en welke de beste is, maar ik wel met de technieken kennis maken in een imperatieve taal (vooral macro`s lijken me erg interessant).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

mmja, ik weet niet precies wat je ermee wilt bereiken, maar misschien dat templates beter geschikt zijn voor wat je wilt doen? (maar goed, je kent java generics, dus als dat zo geweest was dan had je dat wel naar voren gebracht ;))

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Templates zijn niet geschikt voor wat ik in gedachten heb :) Maar ik wil gewoon wat stoeien met die macro`s. Ze worden door veel mensen gezien als evil, maar intussen kom ik steeds meer terug op het gevaar van eenvoud ipv gevaar van een feature.

[edit]
en ik kan nou eindelijk iets maken voor een os (linux + fluxbox = :9~ ) ipv dat het in zo`n gekke vm blijft zitten :P

ojee... overloper?? :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

misschien tijd om je sig aan te passen? :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Zijn er trouwens nog standaarden op het gebied van documentatie? (Trouwens ik kan met die preprocessor ook nog wel postcondities erin genereren (optioneel dus)) die in de 'documentatie' staan.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

niet echt... je zou eens kunnen kijken naar javadoc varianten voor C++, en kijken wat voor comment-style die aanhouden

Overigens snapt doxygen ook javadoc comments :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ok.. javadoc it is going to be..

Maar heb het nu wel weer gehad voor vandaag, ga eens even beginnen met 'the art of the warrior - leadership and strategy from the chinese military classics' :P

Verwijderd

offtopic:
Je bedoelt niet "The Art of War" van Sun Tsu? Dat is idd. een must-read :)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
JonkieXL schreef op 29 oktober 2002 @ 21:28:
macro's worden volgens mij vooral gebruikt voor kleine functies. Het is soms sneller om een macro te gebruiken ipv een functie omdat de stack niet gebruikt hoeft te worden wat een kleine performance winst kan opleveren, maar dit merkt je pas als het stukje macro code in een lus wordt gebruikt.
Soms is dit langzamer, omdat je een compiler geen keus geeft. Bij een inline functie kan de compiler berekenen of het efficienter is om te inlinen (en zelfs zonder "inline" kunnen compilers het tegenwoordig) .

De winst zit 'm overigens in het vermijden van pipeline flushes, dacht ik. Die maken functie calls langzaam.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
* MisterData is ook van Java naar C++ vertrokken :)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
MisterData schreef op 30 oktober 2002 @ 08:23:
[...]
* MisterData is ook van Java naar C++ vertrokken :)
Ik wil het zeker geen vertrekken noemen, maar eerder mijn kennis verruimen. En met java kun je gewoon slecht dingen schrijven voor een os, en aangezien ik echt iets met fluxbox wil gaan doen, lijkt c++ mij een uitstekende taal om ook onder de knie te krijgen.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Waarom moet bij een geparametriseerde class (template) altijd haakjes worden gezet bij een argumentloze constructor. Dus:

PropertyChangeSupport<int> support; //gaat fout
PropertyChangeSupport<int> support ();//gaat goed

En bij niet geparametriseerde classes hoeft dit niet.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Alarmnummer schreef op 30 oktober 2002 @ 10:53:
Waarom moet bij een geparametriseerde class (template) altijd haakjes worden gezet bij een argumentloze constructor. Dus:

PropertyChangeSupport<int> support; //gaat fout
PropertyChangeSupport<int> support ();//gaat goed

En bij niet geparametriseerde classes hoeft dit niet.
Eh, dat hoeft niet. Sterker nog, het werkt niet.
code:
1
PropertyChangeSupport<int> support ();
is een functiedeclaratie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ok..

en nu heb ik het volgende probleem:
code:
1
2
3
4
5
6
class TestModel{
public:

private:
  PropertyChangeSupport<int,TestModel> support;
};

Ik heb hem al geprobeerd met een forward class def. Maar dat hielp niet. En het ligt verder niet aan de parametrisatie, want als ik parametriseer met <int,int> dan is er niets aan het handje.

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34

Een class kan geen instanties hebben van zijn eigen binnen de class zelf. Een class kan wel een pointer naar een object van die class hebben.
Nu weet ik niet hoe het met templates zit, maar misschien kun je het eens zo proberen:
code:
1
PropertyChangeSupport<int, TestModel*> support;

edit:
Html rechten enzo...

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Het werkt wel, maar ik snap niet waarom mijn oplossing niet goed is.

Verwijderd

Alarmnummer>> omdat recursieve typedeclaraties niet mogelijk zijn, een type wordt dan oneindig groot. In java werkt dit anders omdat er impliciet met references gewerkt wordt, C++ doet dat niet. Bij C++ werk je een expliciete referentie, dus (meestal) met een pointer.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik krijg dit keer die listener voor die property change niet voor elkaar. Als ik die listener parametriseer met int,int dan is er niets aan de hand. Maar ik krijg hem met die TestModel dus niet aan de praat.

code:
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
class TestModel{
public:
  void setValue(int newValue){
    int oldValue = _value;
    _value = newValue;
    _support.fire("",oldValue,_value);
  }

  inline int getValue(){return _value;}
  inline PropertyChangeSupport<int,TestModel*> getSupport(){return _support;}
private:
  int _value;
  PropertyChangeSupport<int,TestModel*> _support;// (this);
};


class TestModelListener: public PropertyChangeListener<int,TestModel*>{
public:
  TestListener(){
    cout<<"TestModelListener created\n";
  }

  void propertyChanged(PropertyChangeEvent<int,TestModel*> e){
    cout<<e.getNewValue();
    cout<<"\n";
    cout<<e.getOldValue();
    cout<<"\n";
    cout<<e.getProperty();
    cout<<"\n";
  }
};

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op 30 oktober 2002 @ 12:48:
Een class kan geen instanties hebben van zijn eigen binnen de class zelf. Een class kan wel een pointer naar een object van die class hebben.
Nu weet ik niet hoe het met templates zit, maar misschien kun je het eens zo proberen:
code:
1
PropertyChangeSupport<int, TestModel*> support;

edit:
Html rechten enzo...
het hangt natuurlijk maar net af van de interne definitie van PropertyChangeSupport

als dat zoiets is:
C++:
1
2
3
4
5
6
7
8
9
10
template <class T, class S>
class PropertyChangeSupport
{
private:
    T   value;
    S & parent;

public:
    ...
};


dan werkt het natuurlijk prima

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zie dat ik nog even beter moet kijken naar argumenten van functies, en dan vooral mbv objecten en call by reference en call by value. Daardoor is het laatste voorbeeld sowieso al logisch fout. Ik loop geloof ik te veel objecten onnodig aan te maken.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Hoe zit het trouwens met verschillen tussen methode declaraties in de header en die bij de implementatie? Ik merk dat de compiler niet loopt te gillen als ik in de header er een const X& van maak, en in de implementatie laat ik dit achterwege.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Alarmnummer schreef op 30 oktober 2002 @ 15:20:
Hoe zit het trouwens met verschillen tussen methode declaraties in de header en die bij de implementatie? Ik merk dat de compiler niet loopt te gillen als ik in de header er een const X& van maak, en in de implementatie laat ik dit achterwege.
Dat zijn gewoon twee overloads van dezelfde functie naam, maar het doet niet wat je wil. De header declaratie heeft geen definitie

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zie trouwens dat ik iets te voorbarig ben geweest. Ik heb schijnbaar niet op save gedrukt (is emacs noob), en ik krijg nu wel foutmeldingen *is blij met foutmeldingen* :P

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Waar ik nu eigelijk een beetje tegen aanloop is het per ongeluk vasthouden van referenties. vb:
C++:
1
2
3
4
5
6
class Foo{
public:
   void setA(const string& a){_a = a;}
private
   string& _a;
}


En ik roep nu aan met:
foo.setA("hallo");
Nadat dit statement is afgerond, is het string object weer gedestroyed. Maar Foo heeft nu een referentie naar dat gedestroyde object. Ik zie wel in dat je dat hier op een andere manier moet doen, maar hoe zorg je er voor dat je niet per ongeluk referenties vasthoud van objecten terwijl je dat niet mag doen.

Hoe weet je dus wat je mag doen? Dus mag ik vasthouden of niet?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

dit werkt zo niet :)

Een referentie werkt niet hetzelfde als een pointer. Bij construction (dus als je een nieuwe instantie van Foo aanmaakt), moet je m laten wijzen naar een object, en vanaf dat moment worden alle operaties die je op die referentie uitvoert uitgevoerd op het object waar hij naar wijst.
Als je een variabele wilt hebben die steeds naar wat anders moet wijzen zul je een pointer moeten gebruiken

[nohtml]
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Foo
{
private:
    int & a;

public:
    Foo (int & pA) : a (pA) { }

    void setA (int pA) { a = pA; }
};

int main ()
{
    int i = 3;
    Foo foo (i);

    foo.setA (15);  // i wordt nu op 15 gezet

    return 0;
}

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ok.. maar wat nou als ik gewoon een methode hebt, dus een object argument meekrijgt. En ik hou (voorgoed) een referentie vast naar dat argument. Later wordt dit argument weer afbroken, terwijl er nog wel een referentie naar is. Dus hoe weet je wie verantwoordelijk is voor het afbreken van dat object?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
De reatie van .oisyn is correct, maar mist nog de subtiliteit dat "hallo" geen std::string is, maar daar naar geconvert wordt. De compiler moet een error geven op de assignment van een const& aan een non-const&, juist om deze fout te ondervangen.

Om de originele vraag te beantwoorden; of je een reference kunt gebruiken hangt puur en alleen af van je design. Als je zeker weet dat een object een lifetime heeft die langer is dan de kopie die je van dat object wil maken, dan kun je die kopie vervangen door een reference. Dat is dus typisch het geval bij functieparameters ( de aanroepende functie bestaat zolang de aangeroepen functie runt ), maar bij objecten is het zelden het geval.

Toevallig MSVC6 gebruikt?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik gebruik g++ (gcc). Maar stel dat ik bv een listener voor een bepaalde property op basis van string wil toevoegen:

support.addListener(new FooListener(),"aantal");

In de methode addListener plaats ik in een andere structuur die listener icm die string. Als ik klaar ben met addListener, dan wordt die string weer opgeruimt, terwijl hij al wel in die structuur zit. En dit gaat dus een groot probleem opleveren.

Dus hoe weet je als functie/methode zijnde dat je een referentie mag vast houden?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

dat weet je niet, dat komt gewoon neer op goed design (gebruik van smart pointers kan het een stuk makkelijker maken... zo weinig mogelijk zelf alloceren met new trouwens ook)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zal vanavond me dan eens goed gaan richten op smart pointers (vooral even praktisch toepassen). Ik wil eigelijk zo weinig mogelijk irrelevante problemen hoeven op te lossen en me dus zeker niet bezig houden met de problemen van een taal.

En verder wil ik mijn object ontwerp niet al te veel laten beinvloeden door het wel of niet aanwezig zijn van garbage collection. Dat moet er gewoon vrij los van staan, en het is zonde om allerlei consessies te moeten doen omwille hiervan zodat je object ontwerp minder duidelijk is.

Ik hoop dus een algemene oplossing voor dit probleem te vinden in die smartpointers, zodat je niet iedere keer hoeft te bedenken hoe je het dit keer gaan oplossen.

[ps]
aha.. ook een degelijke uitbreiding op c++
Multi Methods
hoe kun je nog serieus software ontwerpen zonder?? ;)

Verwijderd

Alarmnummer schreef op 30 oktober 2002 @ 17:11:
aha.. ook een degelijke uitbreiding op c++
Multi Methods
hoe kun je nog serieus software ontwerpen zonder?? ;)
Hmm, ik vind het nogal overkill om voor één kleine constructie die ook vrij clean met wat helper templates te maken is een aparte 'compilatie'-fase te introduceren.. :/

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Verwijderd schreef op 30 oktober 2002 @ 18:03:
[...]

Hmm, ik vind het nogal overkill om voor één kleine constructie die ook vrij clean met wat helper templates te maken is een aparte 'compilatie'-fase te introduceren.. :/
Wat bedoel je met een kleine constructie? Ik vind multidispatch eerlijk gezegd erg handig om software mee te ontwerpen omdat je veel makkelijker per geval een oplossing kan aanbieden. En verder vind ik het erg handig om functionaliteit niet in objecten zelf te stoppen :) Data + functionaliteit in 1 object is de ouderwetse kortzichtige manier om software te ontwerpen. Je objecten worden log en groot, je functionaliteit is lastig om te overzien omdat het over een hele hierarchie van objecten verspreid ligt en verder is het toevoegen van functionaliteit ook een drama als je de source van de hierarchie niet hebt. (Trouwens toevoegen van extra classes als je de source van de functionaliteit niet hebt is ook een drama bij mijn oplossing ;) )

Daarom ben ik dus ook zo blij met multimethods of anders 'multimethods' mbv het visitor design pattern.

  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Alarmnummer schreef op 30 oktober 2002 @ 09:22:
[...]

Ik wil het zeker geen vertrekken noemen, maar eerder mijn kennis verruimen. En met java kun je gewoon slecht dingen schrijven voor een os, en aangezien ik echt iets met fluxbox wil gaan doen, lijkt c++ mij een uitstekende taal om ook onder de knie te krijgen.
Je hebt gelijk ja :) Ik doe bijna nooit meer Java these days, en misschien dat ik het weer es ooit ga gebruiken. Cross-platform enzo klinkt allemaal heel mooi, maar crossplatform programmeren kun je ook met C++ (mits je de goede toolkist en API's gebruikt).

Verwijderd

Alarmnummer schreef op 30 oktober 2002 @ 19:50:
[...]

Wat bedoel je met een kleine constructie?
Dat het niets meer is dan een shortcut voor een setje dynamic_cast's.

Ik heb verder niks tegen zo'n shortcut hoor, als jij er in jouw software graag (erg graag zo te horen ;)) gebruikt van maakt moet je dat vooral doen :).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik heb het volgende probleem

C++:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class TestModel{
public:
  TestModel():_support(this){
    cout<<"TestModel created\n";
  }
.
  ~TestModel(){
    cout<<"TestModel destroyed\n";
  }
 . 
  void setValue(int newValue){
    int oldValue = _value;
    _value = newValue;
    _support.fire("value",oldValue,_value);
  }
.
  inline int getValue(){return _value;}
 . 
  inline PropertyChangeSupport<int,TestModel*> getSupport(){return _support;}
private:
  int _value;
  PropertyChangeSupport<int,TestModel*> _support;
};
.
.
template <typename T, typename S>
class PropertyChangeSupport{
public:
  PropertyChangeSupport(const S& source);

  ~PropertyChangeSupport();

  void addListener(const PropertyChangeListener<T,S>& l, string property);

  void removeListener(const PropertyChangeListener<T,S>& l, string property);

  void fire(string property, const T& oldValue, const T& newValue);

  //S getSource(){return _source;}
private:
  // S _source;
  //  vector<PropertyChangeListener<T,S> >* _listeners;
};
.
.
template <typename T,typename S>
PropertyChangeSupport<T,S>::PropertyChangeSupport(const S& source){
  cout<<"PropertyChangeSupport created\n";
  //  _source = source;
}
.
template <typename T,typename S>
PropertyChangeSupport<T,S>::~PropertyChangeSupport(){
  cout<<"PropertyChangeSupport destroyed\n";
}
.
template <typename T,typename S>
void PropertyChangeSupport<T,S>::addListener(const PropertyChangeListener<T,S>& l,string property){}
.
template <typename T,typename S>
void PropertyChangeSupport<T,S>::removeListener(const PropertyChangeListener<T,S>& l, string property){}
.
template <typename T, typename S>
void PropertyChangeSupport<T,S>::fire(string property, const T& oldValue,const T& newValue){
  PropertyChangeEvent<T,S> p (_source,property,oldValue,newValue);
}


Als ik nu een PropertyChangeSupport rechtstreeks aanmaak, dan is er niets aan de hand. Maar als ik hem maak in die TestModel, dan krijg ik problemen als ik een Model probeer aan te maken. Als ik de model niet aanmaak, dan zijn er geen problemen.

De foutmelding: undefined reference to PropertyChangeSupport<int,TestModel*>::PropertyChangeSupport[in charge](TestModel* const&);

en nog een keer bij de destructor ervan.

Als ik nou altijd die fout kreeg, dan wist ik in ieder geval dat er iets mis wat met propertyChangeSupport. Maar ik krijg dus alleen problemen als ik hem gebruik vanuit TestModel en daarnaast maak ik ook een testmodel aan. Als ik geen testmodel aanmaak, dan is er ook niets aan de hand.

[edit]
Ik ben er intussen achter gekomen dat het heeft te maken met het compiler model voor de templates. Voor de class moet het export keyword komen te staan, maar helaas slikt g++ dit niet :'(

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alarmnummer schreef op 31 oktober 2002 @ 14:06:
[edit]
Ik ben er intussen achter gekomen dat het heeft te maken met het compiler model voor de templates. Voor de class moet het export keyword komen te staan, maar helaas slikt g++ dit niet :'(


bijna geen enkele compiler slikt dat (of je moet Comeau gaan gebruiken), je zult de methoden gewoon in je headers moeten definieren

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
.oisyn schreef op 31 oktober 2002 @ 15:29:

[...]


bijna geen enkele compiler slikt dat (of je moet Comeau gaan gebruiken), je zult de methoden gewoon in je headers moeten definieren
Dit is toch wel een vet grote misser zeg!

Wat kan Comeau trouwens nog meer dan standaard g++?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Comeau is volgens mij de compiler die zich volledig aan de standaard houdt
www.comeaucomputing.com

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Hmmzz.. het lijkt me toch verstandig dat ik dan maar doorga met g++ omdat ik wel iets voor linux wil maken wat iedereen in principe moet kunnen compileren. Maar ik maak veel gebruik van templates, dus alles in de headers maar :'(
Pagina: 1