C++不支持模板化的虚拟成员函数,但我有一个理想的场景.我想知道是否有人有想法如何实现这一目标.
#include <iostream>
class Foo {
public:
virtual void bar(int ){}
// make a clone of my existing data, but with a different policy
virtual Foo* cloneforDB() = 0;
};
struct DiskStorage {
static void store(int x) { std::cout << "DiskStorage:" << x << "\n"; }
};
struct DBStorage {
static void store(int x) { std::cout << "DBStorage:" << x << "\n"; }
};
template<typename Storage>
class FooImpl : public Foo {
public:
FooImpl():m_value(0) {}
template<typename DiffStorage>
FooImpl(const FooImpl<DiffStorage>& copyfrom) {
m_value = copyfrom.m_value;
}
virtual void bar(int x) {
Storage::store(m_value);
std::cout << "FooImpl::bar new value:" << x << "\n";
m_value = x;
}
virtual Foo* cloneforDB() {
FooImpl<DBStorage> * newfoo = new FooImpl<DBStorage>(*this);
return newfoo;
}
int m_value;
};
int main()
{
Foo* foo1 = new FooImpl<DiskStorage>();
foo1->bar(5);
Foo* foo2 = foo1->cloneforDB();
foo2->bar(21);
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我想克隆Foo implmemetation,但使用不同的Storagepolicy,我必须明确说明每个这样的实现:
cloneforDB()
cloneforDisk()
Run Code Online (Sandbox Code Playgroud)
模板参数会简化它.谁能想到更清洁的方法呢?请关注这个想法而不是示例,因为它显然是一个人为的例子.
通常,如果要使用虚拟模板方法,则意味着类层次结构的设计出现问题.其高级原因如下.
模板参数必须在编译时知道,这就是它们的语义.它们用于保证代码的健全性.
虚函数用于多态,即.在运行时动态调度.
因此,您不能将静态属性与运行时调度混合使用,如果您查看大图,则没有意义.
在这里,您在某处存储某些内容的事实不应该是您的方法类型的一部分,因为它只是一个行为特征,它可能在运行时更改.所以这是错误的,包括在方法的类型信息.
这就是为什么C++不允许这样做:你必须依靠多态来实现这样的行为.
一个简单的方法是将指针Storage作为参数传递给对象(如果你只想为每个类提供一个对象,则为单例),并在虚函数中使用该指针.
这样,您的类型签名不依赖于您的方法的特定行为.并且您可以在运行时更改存储(在此示例中)策略,这实际上是您应该要求的良好实践.
有时,行为可以由模板参数(例如Alexandrescu的策略模板参数)决定,但它是在类型级别而不是方法级别.