2009-03-04 9 views
0

von der Frage fort, die ich hier gefragt: C++ multi-dimensional data handlingSeparate Halter-Klasse aus dem Leser

In meinem Beispiel: Ich habe viele Chips haben, jeder Chip viele Register hat, hat jedes Register viele Zellen und jede Zelle hat viele Transistoren . Ich fragte, ob ich einen komplexen STL-Container für sie verwenden oder vollständige Klassen für sie implementieren sollte. Und wie empfohlen, entschied ich mich, komplette Klassen für sie zu implementieren. Ich habe:

class Chip 
{ 
    map<RegisterLocation, Register> RegistersPerLocation; 
}; 

class Register 
{ 
    map<CellLocation, Cell> CellsPerLocation; 
}; 

// etc.. 

Nun, ich brauche die Daten in den Klassen zu füllen, und ich kann nicht entscheiden: Soll die Daten, die Verantwortung dieser Klassen zu lesen, oder sollten sie wickeln nur die Behälter und das Lesen wird draußen sein.

Ich meine ich eine der folgenden Möglichkeiten wählen: Entweder:

class Chip 
{ 
    map<RegisterLocation, Register> RegistersPerLocation; 
    public: 
    void AddRegisterPerLocation(RegisterLocation, Register); 
}; 
void ReadChipData(Chip & chip) 
{ 
    for (RegisterLocation loc = 0; loc < 10; loc++) 
    { 
     Register reg; 
     ReadReg(reg); 
     chip.AddRegisterPerLocation(loc, reg); 
    } 
}  
void ReadReg(Register & reg) 
{ 
    for (CellLocation loc = 0; loc < 10; loc++) 
    { 
     Cell cell; 
     ReadCell(cell); 
     reg.AddRegisterPerLocation(loc, cell); 
    } 
} 
//etc... 

Oder:

class Chip 
{ 
    map<RegisterLocation, Register> RegistersPerLocation; 
    public: 
    void ReadData(); 
}; 
void Chip::ReadData() 
{ 
    for (RegisterLocation loc = 0; loc < 10; loc++) 
    {   
     Register reg; 
     reg.ReadData(); 
     RegistersPerLocation[loc] = reg; 
    } 
} 
//etc... 
void ReadChipData(Chip & chip) 
{ 
    chip.ReadData(); 
}  

Danke.

Antwort

2

Wenn Sie daran denken, den Leser/Schreiber an die Domänenobjekte zu binden, um dem Verkapselungsprinzip zu folgen, sind Sie bis zu einem gewissen Grad richtig. Aber denken Sie daran: Sie binden nicht nur eine Aktion, sondern ein gültiges Verhalten. Gültig wie in dem Objekt in der Domäne.

Eine andere Sache zu beachten ist Trennung von Bedenken. Serialisierbarkeit ist kein intrinsisches Verhalten von Chip - das Modellieren in das Domänenobjekt wäre unfairer IMO. YMMV.

Trennen Sie das Lesen (und Schreiben) von den Klassen. Wie die Bibliothek tut. Expose Iteratoren, wenn Sie müssen. Und Sie können die überlasten '< < und Betreiber >>' für syntaktischen Zucker;)

Eine kleinere nit auf den Klassen - eine Vorlage basierten Ansatz so vielversprechend aussieht.

Hier ist ein Code, den ich mir ausgedacht habe: Sie können auch Folgendes ausprobieren. (I erfolgreich kompiliert haben und diese auf einem MS VS2005 laufen, aber es überprüfe auf Ihrem System heraus Auch kann jemand den tabbing beheben - zu faul fühlen, dies zu tun. P)

/*+-----------8<----------------------------8<-----------+*/ 
#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <map> 
#include <iterator> 

/* mother template */ 
template<class _Item> 
struct Hardware 
{  
    Hardware() : _myCont(2 + ::rand() % 5) {} 
private: 
    typename vector<_Item> _myCont; 

    // i/o friends 
    template<class _Item> 
    friend ostream& operator<<(ostream& output, 
           const Hardware<_Item>& me); 
    template<class _Item> 
    friend istream& operator>>(istream& in, 
           const Hardware<_Item>& me); 

}; 

/* actual domain objects */ 
/* base object */ 
struct Transistor { 
}; 
/* built objects */ 
typedef Hardware<Transistor> Cell; 
typedef Hardware<Cell> Register; 
typedef Hardware<Register> Chip; 

/* poorman's introspection utility */ 
template<class T> 
const char *who() { return ""; } 

template<> 
const char *who<Transistor>() { return "Transistor"; } 

template<> 
const char *who<Cell>() { return "Cell"; } 

template<> 
const char *who<Register>() { return "Register"; } 

template<> 
const char *who<Chip>() { return "Chip"; } 

/* writer/serialize out */ 
template<class T> 
ostream& operator<<(ostream& out, const Hardware<T>& hw) { 
    // whatever you need to do to write 
    // os << chip works fine, because you will provide a specialization 
    out << "[ " << ::who<Hardware<T>>() << " ]\n\t"; 

    std::copy(hw._myCont.begin(), hw._myCont.end(), 
     std::ostream_iterator<T>(std::cout, "\n\t")); 

    return out; 
} 

/* specialize for base object */ 
ostream& operator<< (ostream& out, const Transistor& hw) { 
    out << "[ " << ::who<Transistor>() << " ]\n"; 
    return out; 
} 


/* reader/serialize in */ 
template<class T> 
istream& operator>>(istream& in, const Hardware<T>& hw) { 
    // whatever you need to do to read 
    // similarly in >> chip works fine, 
    return in; 
} 

// driver showing relationships 
// Chip -> Register -> Cell -> Transistor 
int main() { 
    Transistor t; 
    std::cout << t << std::endl; 
    Cell ce; 
    std::cout << ce << std::endl; 
    Register r; 
    std::cout << r << std::endl; 
    Chip C; 
    std::cout << C << std::endl; 
} 
/*+-----------8<----------------------------8<-----------+*/ 

Caveat: Nicht getestet, daher kann es einige Compilerfehler/Warnungen geben. Aber das sollte dir eine Vorstellung davon geben, was ich zu sagen versuche.

-1

Die Klassen für ihre Serialisierung verantwortlich zu machen ist besser - sobald Sie die Klassenfelder ändern, müssen Sie die selbe Klassenserialisierungsmethode ändern, nicht irgendeinen Leser-/Schreibercode da drüben.

+0

stimme ich überhaupt nicht zu. So erstellen Sie Klassen, die niemals wiederverwendet werden können. Je. Trennen Sie Daten von der Aktion, das ist der richtige Weg. –

+0

Klassen sind genau für bindende Maßnahmen zu Daten. Es wird angenommen, dass die Verkapselung gut ist. – sharptooth

+0

@sharptooth: Sie haben zu einem gewissen Grad Recht. Sie binden nicht nur eine Aktion, sondern ein gültiges Verhalten. Eine andere Sache, die man im Auge behalten sollte, ist die Trennung von Bedenken. Die Serialisierbarkeit ist kein intrinsisches Verhalten eines Chips - das Modellieren in das Domänenobjekt wäre eine unfaire IMO. YMMV :) – dirkgently