与读者分开持有者类别

时间:2009-03-04 09:30:53

标签: c++ oop

继续我在这里提出的问题:C++ multi-dimensional data handling

在我的例子中:我有许多芯片,每个芯片有许多寄存器,每个寄存器有许多单元,每个单元有许多晶体管。我询问是否为它们使用一个复杂的STL容器,或者为它们实现完整的类。而且,按照建议,我选择为他们实现完整的课程。我有:

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

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

// etc..

现在,我需要将数据填充到类中,我无法决定:读取数据是否应该由这些类负责,或者它们是否应该包装容器并且读取将在外部完成。

我的意思是我必须选择以下之一:或者:

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...

或者:

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();
}     

谢谢。

2 个答案:

答案 0 :(得分:2)

如果您正在考虑将读取器/写入器绑定到域对象以遵循封装原则,那么您在某种程度上是正确的。但请记住:您不仅绑定任何操作,还绑定有效行为。对于域中的对象有意义。

要记住的另一件事是分离关注点。可序列化不是Chip的内在行为 - 对域对象进行建模将是不公平的IMO。 YMMV。

将阅读(和写作)与班级分开。正如图书馆那样。如果必须,请公开迭代器。你可以重载'&lt;&lt;&lt;和'&gt;&gt;'语法糖的运算符;)

课程上的一个小问题 - 基于模板的方法看起来很有希望。

这是我编写的一些代码:您也可以尝试以下代码。 (我已经在MS VS2005上成功编译并运行它,但是在你的系统上检查它。此外,有人可以修复标签 - 感觉懒得做到这一点: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<-----------+*/

警告:尚未测试,因此可能存在相当多的编译器错误/警告。但这应该让你知道我想说的是什么。

答案 1 :(得分:-1)

使类对其序列化负责更好 - 一旦更改了类字段,就必须更改相同的类序列化方法,而不是那些读取器/编写器代码。