2016-06-09 55 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,以便外部类能够枚举对象上的公共字段以执行序列化。

相关问题