cereal/_includes/inheritance.markdown
Shane Grant 04ea0fa0f9 Fixing inheritance doc
closes #92
2014-04-15 14:10:56 -07:00

117 lines
4.0 KiB
Markdown

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<BaseT>( this )` for non-virtual inheritance, and `cereal::virtual_base_class<BaseT>( 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 <cereal/types/base_class.hpp>
struct Base
{
int x;
template <class Archive>
void serialize( Archive & ar )
{ ar( x ); }
};
struct Derived : public Base
{
int y;
template <class Archive>
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<Base>( 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 <cereal/types/base_class.hpp>
struct Base
{
int x;
// Note the non-member serialize - trying to call serialize
// from a derived class wouldn't work
};
template <class Archive>
void serialize( Archive & ar, Base & b )
{ ar( b.x ); }
struct Left : virtual Base
{
int l;
template <class Archive>
void serialize( Archive & ar )
{
ar( cereal::virtual_base_class<Base>( this ), l );
}
};
struct Right : virtual Base
{
int r;
template <class Archive>
void serialize( Archive & ar )
{
ar( cereal::virtual_base_class<Base>( this ), r );
}
};
struct Derived : virtual Left, virtual Right
{
int y;
template <class Archive>
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<Left>( this ),
cereal::virtual_base_class<Right>( 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.