Zoals enkelen van jullie wel weten ben ik al een tijdje met een C++ (m'n eerste) project bezig en ben daarbij al tegen een aantal problemen aangelopen. Al eerder had ik een topic geopend over het initialiseren van variabelen en heb na aanleiding van dat topic besloten om een protected init methode te maken.
Nu het project wat vordert blijkt het handiger te zijn om een class op te splitsen. Deze class zit namelijk vol met een berg functionaliteit die in veel gevallen helemaal niet nodig is. Daarnaast moet er een nieuwe class komen die een kleine uitbreiding heeft, maar voor de rest op het absolute minimum van die class gebaseerd kan worden. Om een lang verhaal kort te maken, de class wordt omgezet in een lite versie, een gewone versie en een extended versie en er word een andere class gemaakt die de lite versie derived.
Het probleem
Omdat er in die initialisatie fase nogal veel gebeurt, en elke class een berg constructors heeft heb ik in eerste instantie gekozen voor een init functie. Deze init functie wordt ook aangeroepen op het moment dat ik de class 'vernieuw'. Nu ik de boel opsplits loop ik tegen het probleem aan dat de init functie meerdere keren uitgevoerd kan worden in plaats van 1. Als voorbeeld heb ik ff dit programmatje:
Als ik nu de constructor van Derived aanroep wordt de constructor van Base aangeroepen en met init a op nul gezet. vervolgens wordt init in Derived aangeroepen en b op 0 gezet. So far so good.
Het probleem is nu waneer ik renew() aanroep op Derived. Deze zal alleen b op 0 zetten en a niet. Ik kan natuurlijk in renew() ook Base::init() aanroepen, maar bij de extended versie wordt het dan wel een beetje druk (eerst lite::init() vervolgens gewoon::init() en tot slot de eigen init()).
Ik zou het op kunnen lossen door in init de herarchie te doorlopen, dus bij een aanroep van init telkens ook de init van 'super' aan te roepen, maar dan krijg je het probleem bij de constructoren dat de init van de Base class meerdere keren aangeroepen wordt.
In principe zou dit probleem natuurlijk zo opgelost zijn waneer er zoiets als in java mogelijk was geweest. Hierin kun je bij je bij 'globale' class variabele declaraties gewoon een initiele waarde opgeven, maar uit m'n vorige topic was ik al tot de conclusie gekomen dat dat niet mogelijk was.
Wat wil ik nou?
Aangezien ik nog maar net werkelijk met C++ bezig ben, ben ik nog niet zo heel erg bekend met de conventies en standaarden voor c++-code. Wat is nu eigenlijk de standaard/beste manier? Het liefst schrijf ik zo min mogelijk dubbele code (kan alleen maar voor fouten zorgen, ene deel wel aanpassen en het andere deel vergeten) en maak ik het zo generiek mogelijk (niet dat je je in een derived class van de derived class nog druk moet maken wat er in de base class gebeurt).
Nu het project wat vordert blijkt het handiger te zijn om een class op te splitsen. Deze class zit namelijk vol met een berg functionaliteit die in veel gevallen helemaal niet nodig is. Daarnaast moet er een nieuwe class komen die een kleine uitbreiding heeft, maar voor de rest op het absolute minimum van die class gebaseerd kan worden. Om een lang verhaal kort te maken, de class wordt omgezet in een lite versie, een gewone versie en een extended versie en er word een andere class gemaakt die de lite versie derived.
Het probleem
Omdat er in die initialisatie fase nogal veel gebeurt, en elke class een berg constructors heeft heb ik in eerste instantie gekozen voor een init functie. Deze init functie wordt ook aangeroepen op het moment dat ik de class 'vernieuw'. Nu ik de boel opsplits loop ik tegen het probleem aan dat de init functie meerdere keren uitgevoerd kan worden in plaats van 1. Als voorbeeld heb ik ff dit programmatje:
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
| class Base{ public: Base(); renew(); protected; void init(); private: int a; }; class Derived : public Base { public: Derived(); renew(); protected(); void init(); private: int b; }; Base::Base(){ init(); } void Base::renew(){ init(); } void Base::init() { a = 0; } Derived::Derived() { init(); } void Derived::renew() { // Base::inite(); ?? init() } void Derived::init() { b = 0; // Base::init(); ?? } |
Als ik nu de constructor van Derived aanroep wordt de constructor van Base aangeroepen en met init a op nul gezet. vervolgens wordt init in Derived aangeroepen en b op 0 gezet. So far so good.
Het probleem is nu waneer ik renew() aanroep op Derived. Deze zal alleen b op 0 zetten en a niet. Ik kan natuurlijk in renew() ook Base::init() aanroepen, maar bij de extended versie wordt het dan wel een beetje druk (eerst lite::init() vervolgens gewoon::init() en tot slot de eigen init()).
Ik zou het op kunnen lossen door in init de herarchie te doorlopen, dus bij een aanroep van init telkens ook de init van 'super' aan te roepen, maar dan krijg je het probleem bij de constructoren dat de init van de Base class meerdere keren aangeroepen wordt.
In principe zou dit probleem natuurlijk zo opgelost zijn waneer er zoiets als in java mogelijk was geweest. Hierin kun je bij je bij 'globale' class variabele declaraties gewoon een initiele waarde opgeven, maar uit m'n vorige topic was ik al tot de conclusie gekomen dat dat niet mogelijk was.
Wat wil ik nou?
Aangezien ik nog maar net werkelijk met C++ bezig ben, ben ik nog niet zo heel erg bekend met de conventies en standaarden voor c++-code. Wat is nu eigenlijk de standaard/beste manier? Het liefst schrijf ik zo min mogelijk dubbele code (kan alleen maar voor fouten zorgen, ene deel wel aanpassen en het andere deel vergeten) en maak ik het zo generiek mogelijk (niet dat je je in een derived class van de derived class nog druk moet maken wat er in de base class gebeurt).
[ Voor 0% gewijzigd door Janoz op 17-09-2002 23:19 . Reden: Wat spelfouten :) ]
Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'