我尝试为我的非成员serialize()函数提供A类的getter,因为从成员访问是私有的.
template<typename T> class A { public: A(const T& id) : m_id(id) {} T& getRef() { return m_id; } // not giving good results T getId() { return m_id; } // not giving good results const T& getRef() const { return m_id; } // not giving good results private: // I would like to keep it private T m_id; } namespace boost { namespace serialization { template<class Archive,typename T> void serialize(Archive &ar,A &a,const unsigned int version) { // ar &BOOST_SERIALIZATION_NVP(a.m_id); // I would like to avoid that it works if m_id is public ar &BOOST_SERIALIZATION_NVP(a.GetRef()); // I want this ! } }} // and later I use std::ofstream ofs("test.xml"); boost::archive::xml_oarchive oa(ofs); A<int> a(42); oa << BOOST_SERIALIZATION_NVP(a);
不幸的是,执行时一直告诉我类型为boost :: archive :: xml_archive_exception的未捕获异常 – 当我尝试使用getList(GetRef()或GetId()时,无效的XML标记名称.
如果我公开时直接访问m_id,它的效果很好.
这样做有什么好方法吗?
解决方法
>你可以使用老朋友:
template <typename T> class A { public: A(const T &id) : m_id(id) {} private: template <typename Ar,typename U> friend void boost::serialization::serialize(Ar&,A<U>&,const unsigned); T m_id; }; namespace boost { namespace serialization { template <class Archive,typename T> void serialize(Archive &ar,A<T> &a,const unsigned int) { ar & BOOST_SERIALIZATION_NVP(a.m_id); } } }
>您可以使用getRef()方法.这个
>不需要朋友(少打扰)
>需要make_nvp(因为您不能使用a.getRef()作为XML元素名称
Sadly,having the reference getter break encapsulation in a horrific way. I’d personally prefer to have
m_id
public in the first place,instead.
template <typename T> class A { public: A(const T &id) : m_id(id) {} T& getRef() { return m_id; } T const& getRef() const { return m_id; } private: T m_id; }; namespace boost { namespace serialization { template <class Archive,const unsigned int) { ar & boost::serialization::make_nvp("m_id",a.getRef()); } } }
奖励积分:
>您可以使用’pimpl’样式结构.您可以在A<>内转发声明一个结构:
template <typename T> class A { public: struct access; A(const T &id) : m_id(id) {} private: T m_id; };
这比getRef()方法更少侵入,getRef()方法只是简单地破坏了封装.现在,您可以隐藏此类中的私有访问:
namespace boost { namespace serialization { template <class Archive,const unsigned int version) { A<T>::access::serialize(ar,a,version); } } }
当然,您仍然需要实现它,但这可以在单独的标题中完成,并且不会影响A类<> (或其任何专业):
template <typename T> struct A<T>::access { template <class Archive> static void serialize(Archive &ar,const unsigned int) { ar & BOOST_SERIALIZATION_NVP(a.m_id); } };