alv*_*vas 10 c c++ java serialization
什么是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);
}
Run Code Online (Sandbox Code Playgroud)
可以像Java一样继承任何可序列化的C/C++对象吗?
Gal*_*lik 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';
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
该序列化格式是完全由程序员,您有责任确保您要的类的每一个成员序列化本身是序列化(具有插入/拔出定义的运营商).您还必须处理字段如何分隔(空格或换行或零终止?).
所有基本类型都预先定义了序列化(插入/提取)运算符,但您仍需要注意std::string可能包含(例如)空格或换行符(如果您使用空格或换行符作为字段)分隔符).
对此没有统一的标准。实际上,每个库都可以以不同的方式实现它。以下是一些可以使用的方法:
类必须从通用基类,实现read()和write()虚拟方法派生:
class SuperMan : public BaseObj
{
public:
virtual void read(Stream& stream);
virtual void write(Stream& stream);
};
Run Code Online (Sandbox Code Playgroud)类应该实现特殊的接口-在C ++中,这是通过从特殊的抽象类派生类来完成的。这是先前方法的变化:
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);
};
Run Code Online (Sandbox Code Playgroud)库可能允许(或要求)为给定类型注册“序列化器”。可以通过从特殊的基类或接口创建类,然后为给定类型注册它们来实现它们:
#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());
}
Run Code Online (Sandbox Code Playgroud)序列化器也可以使用函子来实现,例如lambdas:
int main
{
register_class_serializer(SUPERMAN_CLASS_ID,
[](Stream&, const SuperMan&) {},
[](Stream&) -> SuperMan {});
}
Run Code Online (Sandbox Code Playgroud)无需将序列化程序对象传递给某些函数,只需将其类型传递给特殊的模板函数即可:
int main
{
register_class_serializer<SuperManSerializer>();
}
Run Code Online (Sandbox Code Playgroud)类应提供重载的运算符,例如“ <<”和“ >>”。它们的第一个参数是某个流类,第二个参数是out类实例。Stream可以是std::stream,但是这会与这些运算符的默认用法冲突-转换为用户友好的文本格式或从中转换。因为这个流类是专用的(它可以包装std :: stream),否则,如果<<还必须支持库,它将支持替代方法。
class SuperMan
{
public:
friend Stream& operator>>(const SuperMan&);
friend Stream& operator<<(const SuperMan&);
};
Run Code Online (Sandbox Code Playgroud)对于我们的类类型,应该有一些类模板的特殊化。此解决方案可以与<<和>>运算符一起使用-库首先会尝试使用此模板,如果不专门化,则还原为运算符(可以将其实现为默认模板版本,也可以使用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);
}
Run Code Online (Sandbox Code Playgroud)代替类模板库,也可以使用带有全局重载函数的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);
Run Code Online (Sandbox Code Playgroud)C ++语言是灵活的,因此上面所列内容肯定不完整。我坚信有可能发明另一种解决方案。