2016-06-09 67 views
9

什麼是java.io.Serializable的C/C++等價?什麼是java.io.Serializable的C/C++等價?

有很系列化庫的引用:

而且有:

但是確實存在這樣的等價關係嗎?

因此,如果我在Java中有如下的抽象類,那麼C/C++中的可序列化類將如何看起來像?

import java.io.Serializable; 

public interface SuperMan extends Serializable{ 

    /** 
    * Count the number of abilities. 
    * @return 
    */ 
    public int countAbility(); 

    /** 
    * Get the ability with index k. 
    * @param k 
    * @return 
    */ 
    public long getAbility(int k); 

    /** 
    * Get the array of ability from his hand. 
    * @param k 
    * @return 
    */ 
    public int[] getAbilityFromHand(int k); 

    /** 
    * Get the finger of the hand. 
    * @param k 
    * @return 
    */ 
    public int[][] getAbilityFromFinger(int k); 

    //check whether the finger with index k is removed. 
    public boolean hasFingerRemoved(int k); 

    /** 
    * Remove the finger with index k. 
    * @param k 
    */ 
    public void removeFinger(int k); 

} 

可以在任何序列化的C/C++對象只是繼承像Java中?

+5

C++標準庫沒有任何標準庫。其他庫(如我知道的MFC)可能支持序列化。雖然有XML,JSON等序列化庫。 – Ajay

+0

這不是你所要求的,而是根據通常在C++中完成的事情(通常證明相當可行),[boost](http://www.boost.org/doc/libs/1_61_0/libs/)序列化/ doc /)值得一看。 –

+1

我不會尋找基本上是語言級別的Java特性的C++等價物,而是專注於如何處理C++中的序列化。標準的方法可能是相似的,但不一定必須 - 畢竟,C++和Java有不同的內存模型等等。 – Thomas

回答

13

有沒有標準庫類實現序列化Java相同的方式。有一些庫,便於序列但基本需求,你通常通過重載插入提取運營商這樣做你的類序列

class MyType 
{ 
    int value; 
    double factor; 
    std::string type; 

public: 
    MyType() 
    : value(0), factor(0.0), type("none") {} 
    MyType(int value, double factor, const std::string& type) 
    : value(value), factor(factor), type(type) {} 

    // Serialized output 
    friend std::ostream& operator<<(std::ostream& os, const MyType& m) 
    { 
     return os << m.value << ' ' << m.factor << ' ' << m.type; 
    } 

    // Serialized input 
    friend std::istream& operator>>(std::istream& is, MyType& m) 
    { 
     return is >> m.value >> m.factor >> m.type; 
    } 
}; 

int main() 
{ 
    std::vector<MyType> v {{1, 2.7, "one"}, {4, 5.1, "two"}, {3, 0.6, "three"}}; 

    std::cout << "Serialize to standard output." << '\n'; 

    for(auto const& m: v) 
     std::cout << m << '\n'; 

    std::cout << "\nSerialize to a string." << '\n'; 

    std::stringstream ss; 
    for(auto const& m: v) 
     ss << m << '\n'; 

    std::cout << ss.str() << '\n'; 

    std::cout << "Deserialize from a string." << '\n'; 

    std::vector<MyType> v2; 

    MyType m; 
    while(ss >> m) 
     v2.push_back(m); 

    for(auto const& m: v2) 
     std::cout << m << '\n'; 

} 

輸出:

Serialize to standard output. 
1 2.7 one 
4 5.1 two 
3 0.6 three 

Serialize to a string. 
1 2.7 one 
4 5.1 two 
3 0.6 three 

Deserialize from a string. 
1 2.7 one 
4 5.1 two 
3 0.6 three 

系列化格式爲en tirely由程序員,你有責任確保您要連載類的每個成員本身就是序列(定義了一個插入/提取運營商)。你還必須處理字段是如何分開的(空格或換行或零終止?)。

所有的基本類型有系列化插入/提取)運營商預先定義的,但你仍然需要小心之類的東西std::string可以包含(例如)空格或新行(如果您使用空格或換行符作爲您的字段分隔符)。

+0

評論不適用於擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/115109/discussion-on-answer-by-galik-what-is-the-cc-equivalence-of-java-io- serializa)。 –

3

這沒有一個標準。實際上,每個圖書館都可以以不同的方式實施。下面是可以使用的一些方法:

  • 類已被從共同的基類派生和實施read()write()虛擬方法:

    class SuperMan : public BaseObj 
    { 
    public: 
        virtual void read(Stream& stream); 
        virtual void write(Stream& stream); 
    }; 
    
  • 類應該實現特殊的接口 - 在C++此是通過從特殊抽象類派生類來完成的。這是以前的方法的variaton:

    class Serializable 
    { 
    public: 
        virtual Serializable() {} 
        virtual void read(Stream& stream) = 0; 
        virtual void write(Stream& stream) = 0; 
    }; 
    
    class SuperMan : public Man, public Serializable 
    { 
    public: 
        virtual void read(Stream& stream); 
        virtual void write(Stream& stream); 
    }; 
    
  • 文庫可以允許(或需要)註冊爲給定類型的「串行」。

    #define SUPERMAN_CLASS_ID 111 
    
    class SuperMan 
    { 
    public: 
        virtual int getClassId() 
        { 
         return SUPERMAN_CLASS_ID; 
        } 
    }; 
    
    class SuperManSerializer : public Serializer 
    { 
        virtual void* read(Stream& stream); 
        virtual void write(Stream& stream, void* object); 
    }; 
    
    int main() 
    { 
        register_class_serializer(SUPERMAN_CLASS_ID, new SuperManSerializer()); 
    } 
    
  • 串行也可以實現使用函子,例如:它們可以通過從專用基類或接口創建類,然後註冊它們對於給定的類型來實現lambda表達式:

    int main 
    { 
        register_class_serializer(SUPERMAN_CLASS_ID, 
               [](Stream&, const SuperMan&) {}, 
               [](Stream&) -> SuperMan {}); 
    } 
    
  • 強似串行對象的一些功能,它可能是不夠的類型傳遞給特殊的模板功能:

    int main 
    { 
        register_class_serializer<SuperManSerializer>(); 
    } 
    
  • 類應該提供重載運算符,如「< <」和'>>'。他們的第一個參數是一些流類,第二個是類實例。流可以是std::stream,但這會導致與這些運算符的默認用法相沖突 - 轉換爲用戶友好的文本格式和轉換爲用戶友好的文本格式。由於這個流類是一個專用的類(它可以包裝std :: stream),或者庫將支持替代方法,如果還必須支持<<

    class SuperMan 
    { 
    public: 
        friend Stream& operator>>(const SuperMan&); 
        friend Stream& operator<<(const SuperMan&); 
    }; 
    
  • 應該爲我們的類類型專門化一些類模板。該解決方案可與<<>>運營商可以使用 - 庫將首先嚐試使用這個模板,並恢復到運營商,如果它不會被專業(這可以使用SFINAE被實現爲默認模板的版本,或)

    // default implementation 
    template<class T> 
    class Serializable 
    { 
    public: 
        void read(Stream& stream, const T& val) 
        { 
         stream >> val; 
        } 
        void write(Stream& stream, const T& val) 
        { 
         stream << val; 
        } 
    }; 
    
    // specialization for given class 
    template<> 
    class Serializable<SuperMan> 
    { 
        void read(Stream& stream, const SuperMan& val); 
        void write(Stream& stream, const SuperMan& val); 
    } 
    
  • ,而不是類模板庫還可以使用C風格的界面與全球重載函數:

    template<class T> 
    void read(Stream& stream, const T& val); 
    template<class T> 
    void write(Stream& stream, const T& val); 
    
    template<> 
    void read(Stream& stream, const SuperMan& val); 
    template<> 
    void write(Stream& stream, const SuperMan& val); 
    

C++語言是靈活的,所以上面所列內容是肯定不完整。我相信有可能發明另一種解決方案。

3

正如其他答案所提到的那樣,C++沒有接近Java(或其他管理語言)所具有的內置序列化/反序列化功能。這部分是由於C++中最小的運行時類型信息(RTTI)。 C++本身沒有反射,所以每個可序列化的對象必須完全負責序列化。在像Java和C#這樣的託管語言中,該語言包含足夠的RTTI,以便外部類能夠枚舉對象上的公共字段以執行序列化。