11.01
Stau acum si fac niste modificari / optimizari intr-un proiect, scris, de sigur, de altcineva. Si, surpriza, ca de fiecare data cand faci review ( caci asta faci inainte de a te apuca sa modifici jumate din codul care e acolo ) gasesti ceva care nu e in regula si care te deranjeaza… ceva atat de mic… dar…
Deci, sa trec la tema. Dupa cum se stie in Cpp se pot defini mai multi constructori, astfel, un exemplu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Cluster { private: int a; int b; int c; int d; //aceasta clasa contine foarte multe variabile interne public: //constructorul creeaza clasa pornind de la alta clasa Cluster( CAnotherClass *_class ); // ctor de copiere Cluster( Cluster *_cluster ); // ctor default Cluster( ); }; |
La prima vedere, acest cod pare nevinovat, dar daca te uiti in implementarea constructorilor, ar arata cam astfel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Cluster::Cluster( CAnotherClass *_c ) : a( _c->a ) , b( _c->b ) , c( _c->c ) , d( _c ->d ) { /* no code */ } Cluster::Cluster( Cluster *_c ) : a( _c->a ) , b( _c->b ) , c( _c->c ) , d( _c ->d ) { /* no code */ } Cluster::Cluster( ) : a( 0 ) , b( 0 ) , c( 0 ) , d( 0 ) { /* no code */ } |
in fine, mai pui si constructorul de copiere… si ai 100 de linii de cod cu constructori doar.
Partea nasoala apare doar atunci cand vrei sa adaugi / scoti un membru nou din clasa… ceea ce inseamna ca trebui sa modifici toti constructorii… Poate nu e o problema modificarea constructorilor, dar ce faci daca uiti sa faci modificarile intr-un constructor ( daca ai multe surse se poate intimpla foarte des ).
Pentru a face putin ordine in toti constructorii se procedeaza astfel :
1. se alege o functie ( doar una, posibil privata ) care va avea rolul de a atribui valori membrilor privati
1 | Cluster::set( int a, int b, int c, int d ); |
2. celalti constructori apeleaza doar functia de set definit la punctul 1.
1 2 3 4 5 6 7 8 9 10 11 12 | Cluster::Cluster( CAnotherClass *_c ) { set( _c->a, _c->b, _c->c, _c->d ); } Cluster::Cluster( Cluster *_c ) { set( _c->a, _c->b, _c->c, _c->d ); } Cluster::Cluster( ) { set( 0, 0, 0, 0 ); } |
Prin o astfel de abordare a problemei aveti doar de castigat din urmatoarele motive:
1. atunci cand adaugi un membru nou in clasa, modifici functia set, iar functiile care folosesc functia set o sa dea eroare la compilare ( compilatorul aici e un ajutor pentru tine, iar in celalalt caz trebuie sa modifici manual in fiecare constructor cu posibilitatea ca poti sa omiti undeva modificarile, compilatorul nu iti da nici o eroare, iar la rulare se poate apela un constructor care nu l-ai update-at si care ti-a lasat noua variabila neinitializata ).
2. daca la un moment dat iti dai seama ca o variabila trebuie tratata mai speciala, sa ii faci nishte prelucrari inainte, atunci acest cod nou o sa il scrii doar in functia de set, nu o sa duplici mai apoi codul in toti constructorii.
3. clasa este mult mai bine structurata si ofera o logica celui care o sa ii face review mai tarziu.
cred ca atat.