1<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<!-- 4(C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . 5Use, modification and distribution is subject to the Boost Software 6License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7http://www.boost.org/LICENSE_1_0.txt) 8--> 9<head> 10<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 11<link rel="stylesheet" type="text/css" href="../../../boost.css"> 12<link rel="stylesheet" type="text/css" href="style.css"> 13<title>Serialization - Private Base Classes</title> 14</head> 15<body link="#0000ff" vlink="#800080"> 16<table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header"> 17 <tr> 18 <td valign="top" width="300"> 19 <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3> 20 </td> 21 <td valign="top"> 22 <h1 align="center">Serialization</h1> 23 <h2 align="center">Private Base Classes</h2> 24 </td> 25 </tr> 26</table> 27<hr> 28In many cases, serialization of private or protected base classes present no special problems. 29This is true for both simple classes and types as well as pointers to those 30classes and types. That is, the following program compiles and runs exactly as one would expect. 31<pre><code> 32/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 33// test_private_base.cpp 34 35// (C) Copyright 2009 Eric Moyer - http://www.rrsd.com . 36// Use, modification and distribution is subject to the Boost Software 37// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 38// http://www.boost.org/LICENSE_1_0.txt) 39 40#include <fstream> 41#include <boost/config.hpp> 42#if defined(BOOST_NO_STDC_NAMESPACE) 43namespace std{ 44 using ::remove; 45} 46#endif 47 48#include <boost/serialization/access.hpp> 49#include <boost/serialization/base_object.hpp> 50#include <boost/serialization/export.hpp> 51 52class Base { 53 friend class boost::serialization::access; 54 int m_i; 55 template<class Archive> 56 void serialize(Archive & ar, const unsigned int version){ 57 ar & BOOST_SERIALIZATION_NVP(m_i); 58 } 59protected: 60 bool equals(const Base &rhs) const { 61 return m_i == rhs.m_i; 62 } 63 Base(int i = 0) : 64 m_i(i) 65 {} 66}; 67 68class Derived : private Base { 69 friend class boost::serialization::access; 70private: 71 Base & base_cast(){ 72 return static_cast<Base &>(*this); 73 } 74 template<class Archive> 75 void serialize(Archive & ar, const unsigned int version){ 76 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); 77 } 78public: 79 bool operator==(const Derived &rhs) const { 80 return Base::equals(static_cast<const Base &>(rhs)); 81 } 82 Derived(int i = 0) : 83 Base(i) 84 {} 85}; 86 87int 88main( int /* argc */, char* /* argv */[] ) 89{ 90 const char * testfile = boost::archive::tmpnam(NULL); 91 92 // serialize Derived and Base 93 Derived a(1), a1(2); 94 { 95 test_ostream os(testfile); 96 test_oarchive oa(os); 97 oa << boost::serialization::make_nvp("a", a); 98 } 99 { 100 test_istream is(testfile, TEST_STREAM_FLAGS); 101 test_iarchive ia(is, TEST_ARCHIVE_FLAGS); 102 ia >> boost::serialization::make_nvp("a", a1); 103 } 104 std::remove(testfile); 105 106 if(a != a1) 107 return 1; 108 109 // serialize Derived and Base 110 Derived *ta = &a; 111 Derived *ta1 = NULL; 112 { 113 test_ostream os(testfile); 114 test_oarchive oa(os); 115 oa << boost::serialization::make_nvp("ta", ta); 116 } 117 { 118 test_istream is(testfile, TEST_STREAM_FLAGS); 119 test_iarchive ia(is, TEST_ARCHIVE_FLAGS); 120 ia >> boost::serialization::make_nvp("ta", ta1); 121 } 122 std::remove(testfile); 123 if(*ta != *ta1) 124 return 1; 125 126 return 0; 127} 128</code></pre> 129Difficulties start to occur when the base class is made polymorphic by the designation 130of one or more functions as "virtual". If a class is polymorphic, the library 131presumes that one will want the ability to serialize a derived class through 132a pointer to the base class. Included in the macro 133<code> 134BOOST_SERIALIZATION_BASE_OBJECT_NVP 135</code> 136is code which links derived and base class definitions in tables used to serialize 137derived classes through pointers to a polymorphinc base class. This code requires 138the ability to invoke 139<code> 140static_cast<Base &>(Derived &) 141</code> 142which C++ will only permit from within the derived class if the base class is 143private or protected. The program will fail to compile with an error message 144indicating invalid cast. 145<p> 146In order for this 147code compiler the following alteration must be made: 148<pre><code> 149 template<class Archive> 150 void serialize(Archive & ar, const unsigned int version){ 151 //ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); 152 ar & boost::serialization::make_nvp( 153 "Base", 154 static_cast<Base &>(*this) 155 ); 156 } 157</code></pre> 158With this change the program will now compile. 159<p> 160If we made one of the functions of <code>Base></code> <code>virtual</code> 161in order to use the "export" functionality of the serialization library and permit serialization through 162a pointer the the base class, we'll be disappointed. Without the ability to 163cast to the base class, we can't use the functionality. 164<hr> 165<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2015. 166Distributed under the Boost Software License, Version 1.0. (See 167accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 168</i></p> 169</body> 170</html> 171