| <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <html> |
| <!-- |
| (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . |
| Use, modification and distribution is subject to the Boost Software |
| License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt) |
| --> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <link rel="stylesheet" type="text/css" href="../../../boost.css"> |
| <link rel="stylesheet" type="text/css" href="style.css"> |
| <title>Serialization - Private Base Classes</title> |
| </head> |
| <body link="#0000ff" vlink="#800080"> |
| <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header"> |
| <tr> |
| <td valign="top" width="300"> |
| <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3> |
| </td> |
| <td valign="top"> |
| <h1 align="center">Serialization</h1> |
| <h2 align="center">Private Base Classes</h2> |
| </td> |
| </tr> |
| </table> |
| <hr> |
| In many cases, serialization of private or protected base classes present no special problems. |
| This is true for both simple classes and types as well as pointers to those |
| classes and types. That is, the following program compiles and runs exactly as one would expect. |
| <pre><code> |
| /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
| // test_private_base.cpp |
| |
| // (C) Copyright 2009 Eric Moyer - http://www.rrsd.com . |
| // Use, modification and distribution is subject to the Boost Software |
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #include <fstream> |
| #include <boost/config.hpp> |
| #if defined(BOOST_NO_STDC_NAMESPACE) |
| namespace std{ |
| using ::remove; |
| } |
| #endif |
| |
| #include <boost/serialization/access.hpp> |
| #include <boost/serialization/base_object.hpp> |
| #include <boost/serialization/export.hpp> |
| |
| class Base { |
| friend class boost::serialization::access; |
| int m_i; |
| template<class Archive> |
| void serialize(Archive & ar, const unsigned int version){ |
| ar & BOOST_SERIALIZATION_NVP(m_i); |
| } |
| protected: |
| bool equals(const Base &rhs) const { |
| return m_i == rhs.m_i; |
| } |
| Base(int i = 0) : |
| m_i(i) |
| {} |
| }; |
| |
| class Derived : private Base { |
| friend class boost::serialization::access; |
| private: |
| Base & base_cast(){ |
| return static_cast<Base &>(*this); |
| } |
| template<class Archive> |
| void serialize(Archive & ar, const unsigned int version){ |
| ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); |
| } |
| public: |
| bool operator==(const Derived &rhs) const { |
| return Base::equals(static_cast<const Base &>(rhs)); |
| } |
| Derived(int i = 0) : |
| Base(i) |
| {} |
| }; |
| |
| int |
| main( int /* argc */, char* /* argv */[] ) |
| { |
| const char * testfile = boost::archive::tmpnam(NULL); |
| |
| // serialize Derived and Base |
| Derived a(1), a1(2); |
| { |
| test_ostream os(testfile); |
| test_oarchive oa(os); |
| oa << boost::serialization::make_nvp("a", a); |
| } |
| { |
| test_istream is(testfile, TEST_STREAM_FLAGS); |
| test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
| ia >> boost::serialization::make_nvp("a", a1); |
| } |
| std::remove(testfile); |
| |
| if(a != a1) |
| return 1; |
| |
| // serialize Derived and Base |
| Derived *ta = &a; |
| Derived *ta1 = NULL; |
| { |
| test_ostream os(testfile); |
| test_oarchive oa(os); |
| oa << boost::serialization::make_nvp("ta", ta); |
| } |
| { |
| test_istream is(testfile, TEST_STREAM_FLAGS); |
| test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
| ia >> boost::serialization::make_nvp("ta", ta1); |
| } |
| std::remove(testfile); |
| if(*ta != *ta1) |
| return 1; |
| |
| return 0; |
| } |
| </code></pre> |
| Difficulties start to occur when the base class is made polymorphic by the designation |
| of one or more functions as "virtual". If a class is polymorphic, the library |
| presumes that one will want the ability to serialize a derived class through |
| a pointer to the base class. Included in the macro |
| <code> |
| BOOST_SERIALIZATION_BASE_OBJECT_NVP |
| </code> |
| is code which links derived and base class definitions in tables used to serialize |
| derived classes through pointers to a polymorphinc base class. This code requires |
| the ability to invoke |
| <code> |
| static_cast<Base &>(Derived &) |
| </code> |
| which C++ will only permit from within the derived class if the base class is |
| private or protected. The program will fail to compile with an error message |
| indicating invalid cast. |
| <p> |
| In order for this |
| code compiler the following alteration must be made: |
| <pre><code> |
| template<class Archive> |
| void serialize(Archive & ar, const unsigned int version){ |
| //ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); |
| ar & boost::serialization::make_nvp( |
| "Base", |
| static_cast<Base &>(*this) |
| ); |
| } |
| </code></pre> |
| With this change the program will now compile. |
| <p> |
| If we made one of the functions of <code>Base></code> <code>virtual</code> |
| in order to use the "export" functionality of the serialization library and permit serialization through |
| a pointer the the base class, we'll be disappointed. Without the ability to |
| cast to the base class, we can't use the functionality. |
| <hr> |
| <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2015. |
| Distributed under the Boost Software License, Version 1.0. (See |
| accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| </i></p> |
| </body> |
| </html> |