Наилучшая практика хранения данных классов в файлах с произвольным доступом

В С данные обычно организованы в виде struct тип данных. Это очень удобно сохранить в файле произвольного доступа, потому что вы можете просто перейти к записи, которую вы хотите использовать sizeof на структуре.

Что мне не ясно, каков наилучший подход для этого в C ++, где у вас есть класс с данными (вместе с некоторыми функциями-членами, которые, конечно, не нужно сохранять). Непосредственное хранение класса кажется неправильным, потому что, конечно, это будет включать указатели на функции и такие вещи, которые являются мусором, когда-то сохраненным в файле.

Другой подход, который я мог бы придумать, — это изменение данных членов внутри класса, которые необходимо сохранить, на structи измените функции доступа, чтобы заглянуть во внутреннюю структуру данных. Кажется, что это немного переплетено, но, кажется, единственный логичный способ избежать дублирования каждого поля дважды (один раз в отдельном struct и один раз в классе).

Это, конечно, не работает, когда у вас есть наследование, и производный класс добавляет новые поля. Хотя это вряд ли является проблемой, специфичной для C ++ и файлов с произвольным доступом, и с ней сталкиваются во многих других подходах Object Persistence (включая популярные пакеты ORM в других языках программирования) с различные возможные стратегии даже при сохранении в таблицу базы данных, например.

Есть ли какой-то «стандартный стандарт», который люди обычно используют в C ++ для сохранения данных классов в файлах? Без необходимости копировать вещи повсюду?

-1

Решение

Краткий ответ: это зависит

Средний ответ: все зависит от того, может ли структура C быть непосредственно сериализуемой или нет.

Длинный ответ: если класс A это просто Plain Old Data, он будет сериализуемым, как вы могли бы сделать со структурой C, то есть двоичное копирование и загрузка sizeof(A) байт. Класс — это объект POD, если он содержит только элементы или массивы примитивного типа и / или подобъекты, которые сами являются POD. У него могут быть методы или статические методы, но нет виртуального методы (даже не виртуальный деструктор).

Например, допустимы массивы char, но нет указателя, строки, ссылки и (вообще говоря) объекта из стандартной библиотеки (в частности, нет std :: string).

Конечно, поскольку он непосредственно хранит и загружает двоичные представления данных, он определенно не будет переносимым между различными архитектурами, но может использоваться для локального сохранения состояния.

3

Другие решения

В C ++ единственная разница между struct а также class их видимость по умолчанию; struct по умолчанию публичный, а class по умолчанию частный. Все, что вы можете сделать с struct может быть сделано с class, Оба могут иметь конструкторы, деструкторы, функции-члены, базовые типы, виртуальные члены и т. Д.

Пока тип является тривиально копируемым (то есть тип имеет тривиальный деструктор, конструктор копирования, конструктор перемещения, оператор назначения копирования и оператор назначения перемещения) или тип POD, если вы используете C ++ 98, тогда он может быть сериализовать в файл так же, как в C. Обратите внимание, что любой тип с виртуальными членами или тот, который наследует (виртуально или иным образом) от типа с виртуальными членами, копировать невозможно.

Редактировать: не виртуальные функции-члены не влияют на макет типа. Указатели на такие функции не хранятся в самих объектах.

2

При условии, что все функции-члены не имеют состояния (статические локальные переменные не определены в функциях-членах), нет различий между классами C ++ и структурами в стиле C: вы сериализуете только данные-члены для каждого экземпляра класса.

Для дальнейшего уточнения, когда вы пишете сериализатор (или чаще используете библиотеку сериализации), вы никогда не сохраняете виртуальную таблицу, потому что в этом нет смысла: только данные-члены относятся к экземпляру объекта, тогда как виртуальная таблица определяется классом. ,
Таким образом, единственное реальное влияние наличия виртуальных функций состоит в том, что вы больше не имеете дело с POD-объектом: вы не можете просто выгрузить всю структуру памяти на диск и должны сериализовать экземпляр класса одно поле за другим

0
По вопросам рекламы [email protected]