Inheritance =========== cereal fully supports serializing classes that use inheritance. This page is concerned with how to serialize base classes from a derived class. Another important and related feature of inheritance, polymorphism, is discussed [elsewhere](polymorphism.html). --- ### TLDR Version Archive casted versions of derived classes within your serialize functions instead of calling serialize functions directly. Use `cereal::base_class( this )` for non-virtual inheritance, and `cereal::virtual_base_class( this )` for virtual inheritance. --- ## Normal Inheritance When inheriting from objects without using virtual inheritance (e.g. `struct Derived : public Base`), the recommended method is to utilize `cereal::base_class` to cast the derived class to the base class. This is the preferred method over calling a base class's serialize function directly since it may have any one of four different methods for serialization (see [serialization functions](serialization_functions.html)). This is also preferred over using `static_cast`, since static casting will not work in situations where the base class is abstract. Here is an example of how to do this: ```cpp #include struct Base { int x; template void serialize( Archive & ar ) { ar( x ); } }; struct Derived : public Base { int y; template void serialize( Archive & ar ) { // We pass this cast to the base type for each base type we // need to serialize. Do this instead of calling serialize functions // directly ar( cereal::base_class( this ), y ); } }; ``` --- ## Virtual Inheritance In virtual inheritance, only one copy of each base class will be contained within a derived object. cereal provides a method for tracking virtual base classes, preventing multiple copies from being serialized. If `cereal::base_class` were used in a situation where the same base class appeared in more than one traversal of the class hierarchy, it could potentially result in duplicate information being serialized. To prevent this, use `cereal::virtual_base_class`, which lets cereal track the instantiation of base objects for a derived class, ensuring that only one copy of each base class is serialized. ```cpp #include struct Base { int x; // Note the non-member serialize - trying to call serialize // from a derived class wouldn't work }; template void serialize( Archive & ar, Base & b ) { ar( b.x ); } struct Left : virtual Base { int l; template void serialize( Archive & ar ) { ar( cereal::virtual_base_class( this ), l ); } }; struct Right : virtual Base { int r; template void serialize( Archive & ar ) { ar( cereal::virtual_base_class( this ), r ); } }; struct Derived : virtual Left, virtual Right { int y; template void serialize( Archive & ar ) { // Since we've used virtual inheritance and virtual_base_class, // xCEREAL will ensure that only one copy of each base class // is serialized ar( cereal::virtual_base_class( this ), cereal::virtual_base_class( this ), y ); } }; // With virtual inheritance and cereal::virtual_base_class, x, l, r, and y will be serialized exactly once. // If we had not used virtual_base_class, two copies of the base class may have been serialized, // resulting in duplicate x entries. ``` --- ## Inheriting Serialization Functions In cases where serialization functions are inherited, it is possible to get into situations where you may have more than one type of serialization function (e.g. serialize and a load/save pair) for a type. Since cereal does not like this, a static assertion will cause compilation to fail. In situations like this, you can tell cereal to explicitly use certain serialization types for your class. This is detailed in the [serialization functions](serialization_functions.html#inheritance) section of the documentation.