2015-06-02 13 views
5

Tôi đã cố gắng cung cấp getters của lớp A cho chức năng serialize() không phải thành viên của mình vì truy cập từ các thành viên là riêng tư.Nhận các thành viên dữ liệu cá nhân cho việc tuần tự hóa không xâm nhập C++

Đáng tiếc là việc thực hiện giữ nói với tôi uncaught exception of type boost::archive::xml_archive_exception - Invalid XML tag name khi tôi cố gắng sử dụng thu khí hoặc GetRef() hoặc GetId().
Nó hoạt động tốt nếu tôi truy cập trực tiếp đến m_id khi nó là công khai.

Có bất kỳ cách thoải mái làm như vậy?

Trả lời

11
  1. Bạn có thể sử dụng những người bạn cũ thời tốt:

    Live On Coliru

    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); 
        } 
    } 
    } 
    

  2. Bạn có thể sử dụng phương pháp getRef(). Đây

    • không đòi hỏi bạn (ít xâm nhập)
    • đòi hỏi make_nvp (vì bạn không thể sử dụng a.getRef() như một tên phần tử XML

    Đáng buồn thay, có giờ nghỉ đóng gói tài liệu tham khảo getter trong một Thay vào đó, cá nhân tôi muốn có số m_id công khai ở địa điểm đầu tiên.

    Live On Coliru

    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, typename T> 
        void serialize(Archive &ar, A<T> &a, const unsigned int) 
        { 
         ar & boost::serialization::make_nvp("m_id", a.getRef()); 
        } 
    } 
    } 
    

    Điểm thưởng:

  3. Bạn có thể sử dụng một 'pimpl' kiểu struct. Bạn mong có thể khai báo một struct bên A<>:

    template <typename T> 
    class A { 
    public: 
        struct access; 
    
        A(const T &id) : m_id(id) {} 
    private: 
        T m_id; 
    }; 
    

    Đó là ít xâm nhập hơn so với phương pháp getRef() mà chỉ đơn giản phá vỡ đóng gói tất cả các cách.Bây giờ, bạn có thể ẩn truy cập tin bên trong lớp này:

    namespace boost { 
    namespace serialization { 
        template <class Archive, typename T> 
        void serialize(Archive &ar, A<T> &a, const unsigned int version) 
        { 
         A<T>::access::serialize(ar, a, version); 
        } 
    } 
    } 
    

    Tất nhiên bạn vẫn cần phải thực hiện nó, nhưng điều này có thể được thực hiện trong một tiêu đề riêng biệt và không ảnh hưởng đến lớp Một <> (hoặc bất kỳ chuyên ngành của mình) tại tất cả:

    template <typename T> 
    struct A<T>::access { 
        template <class Archive> 
        static void serialize(Archive &ar, A<T> &a, const unsigned int) { 
         ar & BOOST_SERIALIZATION_NVP(a.m_id); 
        } 
    }; 
    

    Xem nó Live On Coliru cũng

+0

Added một "best-of-cả-thế giới" cách tiếp cận mà không phá vỡ đóng gói: ** [Live On Coliru] (http://coliru.stacked-crooked.com/a/5d76b1aa22076a77) **. – sehe

+2

wow. đây là một câu trả lời thực sự tốt đẹp cung cấp các giải pháp khác nhau với ưu và khuyết điểm của họ. Excactly những gì tôi đã nhảy cho;). Cảm ơn bạn ! Quá tệ tôi không thể bỏ phiếu hai lần ... Tôi sẽ thử 1/và 3/lần! – coincoin

+1

Như mọi khi, một câu trả lời tuyệt vời. Ngoài ra, trong khi không phá vỡ đóng gói, và có khả năng một sự vi phạm hoàn toàn của sự tin tưởng, [cách tiếp cận này chứng tỏ] (http://coliru.stacked-crooked.com/a/4424c219ee37aa20) serializing biến thành viên tư nhân. Tốt nhất là tôi có thể nói, nó là tuân thủ spec. Tôi đã buồn bã phải sử dụng điều này khi giao dịch với các thư viện của bên thứ ba.): –

0

Chỉ cần để biết thêm: Trong Để có được giải pháp đầu tiên từ sehe làm việc:

Bạn cần một mong decleration của phương pháp bạn bè như thế này:

// Boost 
#include <boost/serialization/access.hpp> 

class ClassB; 

namespace boost{ 
namespace serialization { 
    template <typename Ar> void serialize(Ar&,ClassB&,const unsigned); 
} 
} 

class ClassB: public ClassA{ 

private: 
    template <typename Ar> friend void boost::serialization::serialize(Ar&,ClassA&,const unsigned); 
public: 
    ClassA(); 
    virtual ~ClassA(); 
}; 

Đã cho tôi một thời gian để có được nó làm việc.

Cheers

+0

Thực ra, để làm mẫu đó, bạn chỉ cần nhấp vào liên kết có nội dung_ ** [Live On Coliru] (http://coliru.stacked-crooked.com/a/1a0004c419ea0e37) ** và thấy bạn không cần tờ khai chuyển tiếp – sehe

Các vấn đề liên quan