[ Wajda.W @ 12.10.2010. 20:06 ] @
Znam da ima slicna tema u vezi sa ovim, ali na njima nije razjasnjeno kako da izbegnem ovo u kodu.
Posto sam procitao da nesto nije u redu kod dizajna ako se ovo priimenjuje u nekom if() ili switch() sto se kod mene desava...

Code:

// Unit.h

class Unit
{
private:
    int myStrength;
    House myOwner;
    bool myRetreat;
public:
    enum unitType {Footmen, Knight};
    Unit();
    virtual ~Unit();
    virtual unitType getType() = 0;
    virtual void setStrength(int strength);
    virtual void setOwner(House owner);
    virtual int getStrength();
    virtual House getOwner();
    virtual void rest();
    virtual void retreat();
    virtual bool getRetreat();
};


//Footmen.h

class Knight : public Unit
{
public:
    Knight();
    virtual ~Knight();
    Unit::unitType getType();
};


//Knight.h

class Footmen : public Unit
{
public:
    Footmen();
    virtual ~Footmen();
    Unit::unitType getType();
};




E sada imam tu dva problema, prvi je sto tip ne bi trebao da se proverava ovako u if prilikom npr popunjavanja niza jedinica, a ja ne znam kako to da izbegnem.
Code:

addUnit(Unit *unit)
{
if(unit->getType() == Unit::Footmen) myUnits[x] = new Footmen();
}


A drugi je sto npr ako se desi da meni treba posle neka treca jedinica koja je izvedena iz klase Unit onda moram da dodajem u enum jos i npr Ship, tj moram da menjam baznu klasu, sto nije takodje dobar stil.

Kako ovo da resim?
[ kiklop74 @ 12.10.2010. 20:32 ] @
Pa nema tu neke posebne magije. Treba samo da koristis Factory pattern.

http://sourcemaking.com/design_patterns/factory_method/cpp/1

tipove ne definisi u baznoj klasi vec izvan nje tako da je ne menjas svaki cas i primeni metod objasnjen na sajtu.
[ Wajda.W @ 12.10.2010. 20:49 ] @
Pa to mi ne daju neku prednost, ili ja ne uvidjam...
I u tom primeru ja opet moram da unapred znam kakve cu sve izvedene klase imati iz osnovne klase da bi napravio program...
[ deerbeer @ 12.10.2010. 21:06 ] @
Napravi jednu cisto vitualnu metodu create u unit klasi :
Code:

virtual Unit* create() = 0 ; 

u svakoj izvedenoj klasi bilo bi :

Code:
 
virtual Unit* Footmen ::create()  { 
return new Footman () ; 
}


onda metoda addUnit bi izgledala :
Code:
 
addUnit(Unit *unit){
   myUnits[x] = unit->create() ;
}

[ Wajda.W @ 12.10.2010. 21:11 ] @
Hvala deerbeer! :)
Sad sam shvatio. :)
[ Wajda.W @ 12.10.2010. 21:42 ] @
Samo me jos interesuje ako na primer imam metodu tipa:
Code:

int getNumberOfKnights()
{
}


Interesuje me kako da sada proveravam koliko instanci iz niza myUnits je tipa Knight?
Da ostavim ovo sa enumeracijom ili ima neko elegantnije i bolje resenje?
[ deerbeer @ 12.10.2010. 21:47 ] @
http://en.wikipedia.org/wiki/Visitor_pattern
[ NaN @ 13.10.2010. 00:00 ] @
Vajda, Gruja je. Ako sam ja dobro shvatio, treba ovako da ide:

Unit.h
Code:
class Unit
{
...
virtual void accept(Visitor*) = 0; //novo
};



Knight.h
Code:

class Knight : public Unit
{
...
virtual void accept(Visitor*); //novo
};


Knight.cpp
Code:

...
void Knight::accept (Visitor* v) {v->visit(this);} //novo


Isto to dodas i za Footmana i za Ship, da ne pisem sve to sad.


I onda:

Visitor.h
Code:

class Visitor 
{
public:
    virtual ~Visitor(){}
    virtual void visit(Footmen*) = 0;
    virtual void visit(Knight*) = 0;
    virtual void visit(Ship*) = 0;
}


CounterVisitor.h
Code:

class CounterVisitor : public Visitor 
{
public:
    virtual void visit(Footmen*);
    virtual void visit(Knight*);
    virtual void visit(Ship*);
    CounterVisitor();
private:
int f_count, s_count, k_count;
}


I konacno CounterVisitor.cpp
Code:

void CounterVisitor::visit(Footmen* f) {f_count++;}
void CounterVisitor::visit(Knight* k) {k_count++;}
void CounterVisitor::visit(Ship* s) {s_count++;}

CounterVisitor::CounterVisitor() { f_count = k_count = s_count = 0; }


Tako da u buducnosti u svakoj klasi samo moras da stavis accept i dalje menjas samo ove visitore (npr kada dodas novu klasu, katapult ili statijaznam).
[ Wajda.W @ 13.10.2010. 09:40 ] @
Ok, hvala Grujo. :)