Toon posts:

[C++]Algemene basisklasse

Pagina: 1
Acties:

Verwijderd

Topicstarter
In een bepaald programma dat ik ontwikkel werk ik volledig object-geörienteerd. Nu heb ik het volgende bedacht:

Stel dat je alle (belangrijke) klassen gaat afleiden van een basisklasse CUnknown. Op zich gaat CUnknown weinig doen, maar als er staat "#define DEBUG", dan start hij een log en kijkt hij welke klasse er zich registreert.

Een voorbeeldje?

(nota: ik heb hier enkel de belangrijkste items gezet)
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
class CUnknown
{
        /**
         * Constructor.
         */
        CUnknown() : iRefCount(0), strDebugName("")
        {
        }

        /**
         * Destructor.
         */
        virtual ~CUnknown()
        {
            #ifdef DEBUG
                if (iRefCount!=0)
                {
                    logDebug.writeLn("Class: forgotten registration: %s (reference count %d)", strDebugName.c_str(), iRefCount);
                }
            #endif
        }
        /**
         * Register the class.
         * \param strName class name.
         */
        void Register(string strName)
        {
            strDebugName = strName;
            ++iRefCount;
            #ifdef DEBUG
                logDebug.writeLn("Class: registered: %s (reference count %d)", strDebugName.c_str(), iRefCount);
            #endif
        }

        /**
         * Unregister the class.
         * \return true if succes.
         */
        bool Unregister()
        {
            --iRefCount;
            #ifdef DEBUG
                logDebug.writeLn("Class: unregistered: %s (reference count %d)", strDebugName.c_str(), iRefCount);
            #endif
            return true;
        }
};

class Blaat
{
    Blaat()
    {
        #ifdef DEBUG
            Register("Blaat klasse");
        #endif
    }

    ~Blaat()
    {
        #ifdef DEBUG
            Unregister();
        #endif
    }
};


In het logboek wordt er dus (bij debug modus) weggeschreven welke klasse(types) zich registeren. Als het programma crasht bij het creëren van een kasse (via "new" bvb), dan kan je in het log terugvinden bij welke klasse het programma is gecrasht.

Wat ik me afvraag:
Vinden jullie dit een goede werkwijze of is dit pure tijdverspilling?

[ Voor 3% gewijzigd door Verwijderd op 05-11-2004 21:23 . Reden: ";" ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 16-05 23:29
Misschien dat je dit eens moet combineren met RTTI (RunTime Type Information), dan kun je als het goed is vanzelf je classname ophalen :)

[ Voor 13% gewijzigd door MisterData op 05-11-2004 21:31 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja, dit heeft ook een naam...veel frameworks werken zo (om over Java maar te zwijgen). Het heeft nog wel meer nut, je kan bv elk object een id geven om ze dan over het netwerk te streamen. Of bepaald standaard werk voor remote procedures, etc.

Of het goed of slecht is hangt ervan af wat je wilt doen...je kan tegen problemen aanlopen met inheritance. Dat is deels op te lossen door virtual inheritance, maar blijft een gedoe...je loopt tegen "the dreaded diamond" op: Zowel class A als class B zijn children van CUnknown, en nu leidt je class C af van A en B...wat unregistered C dan bij destruction? A, of B, of allebei? Klopt je ref count dan nog wel? etc. (in Java is dat allemaal prima, omdat daar geen multiple inheritance bestaat)

[ Voor 59% gewijzigd door Zoijar op 05-11-2004 22:18 ]


Verwijderd

Topicstarter
MisterData schreef op 05 november 2004 @ 21:30:
Misschien dat je dit eens moet combineren met RTTI (RunTime Type Information), dan kun je als het goed is vanzelf je classname ophalen :)
Das wel interessant, ik lees er morgen wel verder over (google enzo).
Zoijar schreef op 05 november 2004 @ 22:13:
Ja, dit heeft ook een naam...veel frameworks werken zo (om over Java maar te zwijgen). Het heeft nog wel meer nut, je kan bv elk object een id geven om ze dan over het netwerk te streamen. Of bepaald standaard werk voor remote procedures, etc.

Of het goed of slecht is hangt ervan af wat je wilt doen...je kan tegen problemen aanlopen met inheritance. Dat is deels op te lossen door virtual inheritance, maar blijft een gedoe...je loopt tegen "the dreaded diamond" op: Zowel class A als class B zijn children van CUnknown, en nu leidt je class C af van A en B...wat unregistered C dan bij destruction? A, of B, of allebei? Klopt je ref count dan nog wel? etc. (in Java is dat allemaal prima, omdat daar geen multiple inheritance bestaat)
Hmz, voorlopig heb ik geen multiple inheritance... maar dat zou inderaad een probleem kunnen worden.
Anderzijds geef ik enkel de "bovenliggende" klassen de afleiding van CUnknown, ik ga niet elke klasse hiervan afleiden, omdat dit dan een overhead aan info geeft... Stel dat je een vector klasse hebt en je maakt 10.000 vectoren (vr een spel) aan, die elk afgeleid zijn van CUnknown, dan zou je nogal wat overhead krijgen (van die strings en ints die CUnknown bevat).
Maar ik besef nu ook dat het niet goed is om eigelijk selectief te werken en uitzonderingen te maken, want dan is er geen algemene regel meer...

*twijfelt nog steeds*

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Ik snap niet helemaal wat je wilt, is iRefCount een statische variabele? Als het een instance variabele is zal het namelijk altijd 1 zijn.
De debugname is een beetje overbodig aangezien je dit ook kan doen met een virtual method die elke classe implementeert (bv virtual std::string GetDebugString()). Voordeel hiervan is dat je de data niet voor elke instantie hoeft op te slaan.

Maar ik zou zeggen kijk eens naar C# of Java, deze talen hebben allebei een structuur waarbij alle classen zijn afgeleid van een enkele root class. Dat is ongeveer wat je wilt. Ik merk trouwens wel dat ik in C++ minder behoefte blijk te hebben aan een rootclass dan in C# of Java, het grootste verschil is dat je in C++ templates kan gebruiken voor je containers. In C# bijvoorbeeld zijn de containers niet strongly-typed waardoor je dus wel een rootclass moet hebben.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
En dan hebben we het nog niet over de al bestaande classes. Hoe wil je int afleiden van CUnknown? Of std::vector<CMyClass> ?

Wil je ook traits classes e.d. afleiden van CUnknown? classes met alleen static methods?

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


Verwijderd

Topicstarter
MSalters schreef op 06 november 2004 @ 09:56:
En dan hebben we het nog niet over de al bestaande classes. Hoe wil je int afleiden van CUnknown? Of std::vector<CMyClass> ?

Wil je ook traits classes e.d. afleiden van CUnknown? classes met alleen static methods?
Er stond toch dat ik dat niet zo doen?
Anderzijds geef ik enkel de "bovenliggende" klassen de afleiding van CUnknown, ik ga niet elke klasse hiervan afleiden, omdat dit dan een overhead aan info geeft...
@ Orphix:
iRefCount is niet statisch. Het bekijkt gewoon hoeveel keer een klasse zich registreert (als dat 2x is, dan heb je een probleem ;))
Deze klasse gebruik ik enkel bij afleiding nr belangrijke klassen, waar de debugnaam wel eens handig kan zijn. (om uit te kunnen zoeken in welke module vd code er ergens een probleem zou kunnen zijn)
Anderzijds besef ik nu dat het mss te vaag is om het op de ene klasse wel toe te passen en de andere niet, dus ga ik het vermoedelijk verwijderen uit m'n code (alle ": public CUnknown").

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het enige wat wij hier tracken zijn memory allocations. De VC++ debugger kan zelf al een naampje bij een instance verzinnen, dus dat is het probleem niet. Maar in een debugbuild checken we dus aan het eind welke allocations nog niet zijn vrijgegeven, en dat wordt dan geoutput, samen met file en linenr waar ze gealloceerd zijn.

Het nare is wel dat je macros moet gaan gebruiken voor new, omdat je anders die file en linenr niet automatisch mee kunt laten 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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op 08 november 2004 @ 11:59:
Het enige wat wij hier tracken zijn memory allocations. De VC++ debugger kan zelf al een naampje bij een instance verzinnen, dus dat is het probleem niet. Maar in een debugbuild checken we dus aan het eind welke allocations nog niet zijn vrijgegeven, en dat wordt dan geoutput, samen met file en linenr waar ze gealloceerd zijn.

Het nare is wel dat je macros moet gaan gebruiken voor new, omdat je anders die file en linenr niet automatisch mee kunt laten geven
Dat is wel handig ja, doe ik ook vaak zoiets. Maar waarom gebruiken jullie niet iets van boundschecker? Die doet dat toch ook, met behulp van de debug info die VS output?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

omdat dat nogal win32 only is en wij ook voor PS2, Gamecube en XBox ontwikkelen :)

[ Voor 6% gewijzigd door .oisyn op 08-11-2004 16:33 ]

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.

Pagina: 1