Предположим, у меня есть шаблонный класс:
template<typename T>
struct Node
{
T val;
Node *next;
};
template<typename T>
class MyClass
{
T data1_;
T data2_;
vector<Node<T> > vi_;
};
Теперь я хочу сериализовать MyClass
на диск, используя другой метод. Например, при использовании сырья C Система вызова записи/чтения или c++ fstream
, или другой подход.
Я ввожу еще один параметр шаблона для этого:
template<typename T,typename SerializerTrait>
class MyClass
{
T data1_;
T data2_;
vector<Node<T> > vi_;
void save()
{
SerializerTrait::save(data1_);
SerializerTrait::save(data2_);
SerializerTrait::save(vi_);
}
};
//serializer
template <typename>
class RawC
{
static FILE *f;
static void save(T t){fwrite(&t,sizeof(t),1,f);}
...
}
template <typename>
class StreamCPP
{
static fstream *f;
static void save(T t){*f<<t);}
...
}
Он может работать. Но это кажется не изящным.
Стратегия - хорошее решение, но функция шаблона не может быть виртуальной.
Есть ли лучший способ сделать это?
Вы можете сделать что-то вроде этого:
template<typename T>
class MyClass
{
template <class SERIALIZER>
void save()
{
SERIALIZER::save(data1_);
SERIALIZER::save(data2_);
SERIALIZER::save(vi_);
}
//or with serializer instance
template <class SERIALIZER>
void save(SERIALIZER & s)
{
s.save(data1_);
s.save(data2_);
s.save(vi_);
}
virtual void save(SerializerDetail * s)
{
s->save(this);
}
};
class SerializerDetail
{
public:
template <class T>
void save(T * p)
{
p->save<SomeSerializer>();//use the first two save functions
//or
p->save(SerializerInstance);//or this of you want it
}
};
template<typename T> Serializer
со статическим методом с именемsave
(аналогично вашимRawC
иStreamCPP
), а затем использовать специализацию шаблона для его реализации для каждого класса, который необходимо сериализовать. Другим подходом могут быть общие классы / интерфейсыDAO
в сочетании сDAOManager
обеспечивающим доступ (это был бы подход, более похожий на OO / java).