有没有一些通用的方法来定义模板成员函数的接口?我想创建一些带有模板成员函数声明的纯抽象基类,这些模板成员函数应该在派生类中被覆盖。比我希望能够通过接口调用派生类的功能。我知道不允许使用虚拟模板成员函数。所以直到现在我想出了以下解决方案(见下文)。我想知道的是我的方法是否是糟糕的设计,或者是否有一些更好的方法可以实现我的目标:
编辑:我想要实现的是一个序列化系统(类似于 boost::serialization)。因此,我希望有一个通用的基本接口函数序列化,可用于保存和加载对象。调用 *do_serialize* 函数时,正确的保存和加载函数调用将由提供的派生存档类确定。
因为我不确定我提供的解决方案,所以我想问一下是否有更好的方法(甚至更简单的方法)来实现我的目标?
接口:
template<typename Derived>
class Archive{
public:
virtual ~Archive() = 0 {}
template<typename T>
Archive& serialize(T t) {
Derived* derived = static_cast<Derived*>(this);
return derived->serialize_derived(t);
}
};
template<typename Derived>
class Writer : public Archive<Derived> {
public:
virtual ~Writer() = 0 {}
template<typename T>
void write(const T& t) {
Derived* derived = static_cast<Derived*>(this);
derived->write_derived(t);
}
};
template<typename Derived>
class Reader : public Archive<Derived> {
public:
virtual ~Reader() = 0 {}
template<typename T>
void read(const T& t) {
Derived* derived = static_cast<Derived*>(this);
derived->read_derived(t);
}
};
派生类:
class BinaryWriter : public Writer<BinaryWriter> {
public:
template<typename T>
BinaryWriter& serialize_derived(T t) {
save(t);
return *this;
}
template<typename T>
void save(T t) {
std::cout << "DerivedWriter::save: " << t << std::endl;
}
template<typename T>
void write_derived(const T& t) {
std::cout << "DerivedWriter::write_derived: " << t << std::endl;
}
};
class BinaryReader : public Reader<BinaryReader> {
public:
template<typename T>
BinaryReader& serialize_derived(T t) {
load(t);
return *this;
}
template<typename T>
void load(T t) {
std::cout << "DerivedWriter::load: " << t << std::endl;
}
template<typename T>
void read_derived(const T& t) {
std::cout << "DerivedReader::read_derived: " << t << std::endl;
}
};
示例测试函数和调用(注意:同样需要调用 Writer/Reader-interface(其他派生的 Writer/Reader-类在此省略(即 TextReader、XMLReader 等)):
template<typename Derived, typename T>
void do_serialize(Archive<Derived>& obj, T t) {
obj.serialize(t);
}
DerivedWriter dw;
DerivedReader dr;
do_serialize(dw, 1);
do_serialize(dr, 2);
输出:
DerivedWriter::save: 1
DerivedReader::read: 2