views:

165

answers:

2

Hi,

When I try to serialize class with protected members, I get the following errors: "cannot access protected member declared in class NetElement". The idea is that I'd like to have one serialization function outside of class definition. What am I doing wrong?

best regards, mightydodol


Here is the code...

// class definition
class NetElement
{
    friend class boost::serialization::access;
protected:
    int nelements;
    int ids;
public:
    static NetElement* New(){return new NetElement;}
    virtual void Delete(){delete this;}
protected:
    NetElement(){};
    ~NetElement(){};
};
// nonintrusive serialize 
template<class Archive>
void serialize(Archive & ar, NetElement& element, const unsigned int version=1)
{
    ar & element.nelements & element.ids;
}

int main(void)
{...
    std::ofstream os("Pipe1.txt");
    boost::archive::text_oarchive oa(os);
    serialize(oa,el/*ref to NetElementObj*/);
 ...
}
+2  A: 

Like any other non-member function, your serialize function can only access the public members of NetElement. If, as is often the case, the public interface doesn't expose enough state to serialize the object, then you'll need to make the serialize function a member.

In this case, though, the state is protected, so you could get to it using an "accessor" class derived from NetElement:

class NetElementAccessor : private NetElement
{
public:
    explicit NetElementAccessor(const NetElement &e) : NetElement(e) {}

    using NetElement::nelements;
    using NetElement::ids;
};

template<class Archive>
void serialize(Archive & ar, NetElement& element, const unsigned int version=1)
{
    NetElementAccessor accessor(element);
    ar & accessor.nelements & accessor.ids;
}

The downside is that this copies the object before serialising it.

Mike Seymour
ok, but what if the NetElement class cannot be changed? What are my options? Sorry, wasn't clear enough...thanx for the quick answer though...
dodol
+2  A: 

You already show yourself changing the class by adding the "friend" line (which does nothing for you without the serialize function being inside the class).

Without being able to change the class, you are stuck with more fragile solutions (here is one I had to do once, that I'm not proud of (but it does show the whole point of protected over private))

#include <boost/archive/text_oarchive.hpp>
#include <fstream>

// class definition
class NetElement
{
protected:
    int nelements;
    int ids;
public:
    static NetElement* New(){return new NetElement;}
    virtual void Delete(){delete this;}
protected:
    NetElement(){};
    ~NetElement(){};
};

class NetElementS : public NetElement
{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & nelements & ids;
    }
};

int main(void)
{
    NetElement *el = NetElement::New();
    std::ofstream os("Pipe1.txt");
    boost::archive::text_oarchive oa(os);
    oa & *reinterpret_cast<NetElementS *>(el);
}
McBeth