Добрый день!
Имеется класс с его закрытыми членами:
class Object
{
protected:
int m_i;
char * m_p;
....
};
Трогать класс нельзя. Методов, возвращающих В некоторый момент понадобилось обратиться к членам этого класса. Например для сериализации. Сохранить текущее состаяние экземпляра. (Напрямую копировать память, занимаемую экземпляром естественно нельзя, сущность на которую указывает m_p тоже нужно сохранить). Предлагается такое решение:
class SObject : public Object
{
public:
void Dump(FILE * stream)
{
fwrite(&m_i, sizeof(int), 1, stream);
fwrite(m_p, strlen(m_p) + 1, 1, stream);
}
};
// Далее где-то в коде:
Object * obj;
FILE * stream;
....
reintrpret_cast<SObject *>(obj)->Dump(stream);
SObject не имеет (не добавляет) виртуальных функций, всё работает отлично.
Но настораживает кастинг вниз. Должно быть это есть признак bad dasign класса Object, но ничего с ним уже не поделаешь. Можно ли найти более элегантный способ решения проблемы?
... << RSDN@Home 1.1.4 @@subversion >>
Здравствуйте, Sir Wiz, Вы писали:
SW>Добрый день!
[skipped]
SW>Но настораживает кастинг вниз. Должно быть это есть признак bad dasign класса Object, но ничего с ним уже не поделаешь. Можно ли найти более элегантный способ решения проблемы?
Можно попробовать так сделать:
class Object
{
protected:
int m_i;
char * m_p;
};
class ObjectDumper
{
public:
void Dump(FILE* stream, Object* a)
{
class Friend: public Object { friend ObjectDumper; };
fwrite(&((Friend*)a)->m_i, sizeof(int), 1, stream);
fwrite(((Friend*)a)->m_p, strlen(((Friend*)a)->m_p) + 1, 1, stream);
}
};
Object a;
ObjectDumper b;
FILE *stream;
b.Dump(stream, &a);
За подробностями
сюдаАвтор: _defrager
Дата: 21.09.04
Здравствуйте, Sir Wiz, Вы писали:
SW>Добрый день!
SW>Имеется класс с его закрытыми членами:
SW>SW>class Object
SW>{
SW>protected:
SW> int m_i;
SW> char * m_p;
SW>....
SW>};
SW>
SW>Трогать класс нельзя. Методов, возвращающих В некоторый момент понадобилось обратиться к членам этого класса. Например для сериализации. Сохранить текущее состаяние экземпляра. (Напрямую копировать память, занимаемую экземпляром естественно нельзя, сущность на которую указывает m_p тоже нужно сохранить). Предлагается такое решение:
SW>SW>class SObject : public Object
SW>{
SW>public:
SW> void Dump(FILE * stream)
SW> {
SW> fwrite(&m_i, sizeof(int), 1, stream);
SW> fwrite(m_p, strlen(m_p) + 1, 1, stream);
SW> }
SW>};
SW>// Далее где-то в коде:
SW>Object * obj;
SW>FILE * stream;
SW>....
SW>reintrpret_cast<SObject *>(obj)->Dump(stream);
SW>
SW>SObject не имеет (не добавляет) виртуальных функций, всё работает отлично.
SW>Но настораживает кастинг вниз. Должно быть это есть признак bad dasign класса Object, но ничего с ним уже не поделаешь. Можно ли найти более элегантный способ решения проблемы?
По сути все сделано нормально, и не надо мудрить. Однако если все же кастинг настораживает
есть более элегантный способ. Можно попробовать так
class SObject : public Object
{
public:
SObject(const Object &obj) { m_i = obj.m_i; m_p = obj.m_p; }
void Dump(FILE * stream) { ...}
};
// Далее где-то в коде:
Object * obj;
FILE * stream;
SObject s_obj(*obj); // ну разумеется здесь имеется ввиду валидный указатель на нормальный объект
s_obj->Dump(stream);
по сути тоже самое, но вроде как изящнее.
С уважением, Алексей.
Сори, ошибочка. конечно же следует читать как
...
Object * obj;
FILE * stream;
SObject s_obj(*obj);
s_obj.Dump(stream);
С уважением, Алексей.
Здравствуйте, <Аноним>, Вы писали:
А>по сути тоже самое, но вроде как изящнее.
Да, спасибо. идея мне нравится.
Только, к сожалению в существующем проекте так сделать не получится — не смогу я объяснить заказчику, почему из-за моих эстетических потребностей отлично работающий модуль станет работать медленнее
... << RSDN@Home 1.1.4 @@subversion >>
Здравствуйте, Sir Wiz, Вы писали:
SW>Здравствуйте, <Аноним>, Вы писали:
А>>по сути тоже самое, но вроде как изящнее.
SW>Да, спасибо. идея мне нравится.
SW>Только, к сожалению в существующем проекте так сделать не получится — не смогу я объяснить заказчику, почему из-за моих эстетических потребностей отлично работающий модуль станет работать медленнее
мы тут копируем только ссылки на объекты (т.е. копирования строки не происходит) + все необходимые объекты создаются на стеке!!! Поэтому если эта операция происходит не более 100000 раз в секунду, то заметить разницу просто не возможно
ну разьве что утилитами