6

我遇到了一个设计问题,其中(在 C++ 中)我希望(非模板类的)模板化成员函数是虚拟的,并且想知道是否有一个好的、优雅的方法来解决这个问题。

情况是这样的,我有处理通用项目机器。我为具有虚拟进程(Item)功能的机器使用抽象基类,以便每台机器都可以定义自己独特的处理方法。问题是这些项目也是“通用的”,因为它们为如何处理它们公开了某些接口。出于某种原因(主要是为了性能......没有 vtable 开销),我想对这些项目使用编译时多态性。这样现在每台机器都会有一个如下界面:

class Machine
{ public:
    template <typename T>
    virtual void process(T& item) = 0; 
};

然而,这在 C++ 中是不可能的,因为模板化的成员函数不能是虚拟的。当然,我可以在 Item 类型 T 上制作机器类模板,但这在更大的设计方案中给我增加了更多的麻烦,而且 Machine 类的其他部分实际上不依赖于 Item……它只是 process() 函数的一个参数.

有没有更好的方法解决这个问题,或者有什么建议可以提供这种处理通用项目系列的通用机器系列(其中项目使用编译时多态性)。就我的设计而言,我是否离题了。

感谢任何建议

4

1 回答 1

3

通常,使用双重调度。

class Machine;
class Item {
public:
    virtual void bounce(Machine& mach);
};
class Machine {
public:
    template<typename T> void process(T& t);
    virtual void process(Item& i) {
        return i.bounce(*this);
    }
};
template<typename T> class CRTPItem {
public:
    virtual void bounce(Machine& mach) {
        return mach.process(*(T*)this);
    }
};
class ConcreteItem : public CRTPItem<ConcreteItem> {
public:
    // blah blah
};

在这种情况下,您不需要整个 ConcreteItem 接口的虚拟开销,它们也不需要任何共同点,只需要bounce通过继承自CRTPItem. 这只是两个 vtable 调用,而不是您最初的一个,而不是需要对 Item 的所有功能进行 vtable 调用,并且如果您可以创建虚拟模板,接口仍然可以保留所有强类型。

于 2013-03-23T21:52:05.073 回答