В С данные обычно организованы в виде struct
тип данных. Это очень удобно сохранить в файле произвольного доступа, потому что вы можете просто перейти к записи, которую вы хотите использовать sizeof
на структуре.
Что мне не ясно, каков наилучший подход для этого в C ++, где у вас есть класс с данными (вместе с некоторыми функциями-членами, которые, конечно, не нужно сохранять). Непосредственное хранение класса кажется неправильным, потому что, конечно, это будет включать указатели на функции и такие вещи, которые являются мусором, когда-то сохраненным в файле.
Другой подход, который я мог бы придумать, — это изменение данных членов внутри класса, которые необходимо сохранить, на struct
и измените функции доступа, чтобы заглянуть во внутреннюю структуру данных. Кажется, что это немного переплетено, но, кажется, единственный логичный способ избежать дублирования каждого поля дважды (один раз в отдельном struct
и один раз в классе).
Это, конечно, не работает, когда у вас есть наследование, и производный класс добавляет новые поля. Хотя это вряд ли является проблемой, специфичной для C ++ и файлов с произвольным доступом, и с ней сталкиваются во многих других подходах Object Persistence (включая популярные пакеты ORM в других языках программирования) с различные возможные стратегии даже при сохранении в таблицу базы данных, например.
Есть ли какой-то «стандартный стандарт», который люди обычно используют в C ++ для сохранения данных классов в файлах? Без необходимости копировать вещи повсюду?
Краткий ответ: это зависит
Средний ответ: все зависит от того, может ли структура C быть непосредственно сериализуемой или нет.
Длинный ответ: если класс A
это просто Plain Old Data, он будет сериализуемым, как вы могли бы сделать со структурой C, то есть двоичное копирование и загрузка sizeof(A)
байт. Класс — это объект POD, если он содержит только элементы или массивы примитивного типа и / или подобъекты, которые сами являются POD. У него могут быть методы или статические методы, но нет виртуального методы (даже не виртуальный деструктор).
Например, допустимы массивы char, но нет указателя, строки, ссылки и (вообще говоря) объекта из стандартной библиотеки (в частности, нет std :: string).
Конечно, поскольку он непосредственно хранит и загружает двоичные представления данных, он определенно не будет переносимым между различными архитектурами, но может использоваться для локального сохранения состояния.
В C ++ единственная разница между struct
а также class
их видимость по умолчанию; struct
по умолчанию публичный, а class
по умолчанию частный. Все, что вы можете сделать с struct
может быть сделано с class
, Оба могут иметь конструкторы, деструкторы, функции-члены, базовые типы, виртуальные члены и т. Д.
Пока тип является тривиально копируемым (то есть тип имеет тривиальный деструктор, конструктор копирования, конструктор перемещения, оператор назначения копирования и оператор назначения перемещения) или тип POD, если вы используете C ++ 98, тогда он может быть сериализовать в файл так же, как в C. Обратите внимание, что любой тип с виртуальными членами или тот, который наследует (виртуально или иным образом) от типа с виртуальными членами, копировать невозможно.
Редактировать: не виртуальные функции-члены не влияют на макет типа. Указатели на такие функции не хранятся в самих объектах.
При условии, что все функции-члены не имеют состояния (статические локальные переменные не определены в функциях-членах), нет различий между классами C ++ и структурами в стиле C: вы сериализуете только данные-члены для каждого экземпляра класса.
Для дальнейшего уточнения, когда вы пишете сериализатор (или чаще используете библиотеку сериализации), вы никогда не сохраняете виртуальную таблицу, потому что в этом нет смысла: только данные-члены относятся к экземпляру объекта, тогда как виртуальная таблица определяется классом. ,
Таким образом, единственное реальное влияние наличия виртуальных функций состоит в том, что вы больше не имеете дело с POD-объектом: вы не можете просто выгрузить всю структуру памяти на диск и должны сериализовать экземпляр класса одно поле за другим