模板可能不是'虚拟'

Jav*_*ier 14 c++ polymorphism virtual templates

鉴于下面的代码,编译器显示一条指向该代码的消息error: templates may not be ‘virtual’.有没有人有关于如何解决这个bug的建议?

template < class FOO_TYPE>
class CFoo{
    public:
        ...
        template < class BAR_TYPE >
        virtual void doSomething( const CBar<BAR_TYPE> &); // here's the error
        ...
        virtual ~CFoo();
    protected:
        MyClass < FOO_TYPE > * m_pClass;
};

template < class FOO_TYPE >
template < class BAR_TYPE >
void CFoo<FOO_TYPE>::doSomething( const CBar<BAR_TYPE> & refBar ){
    ...
}
Run Code Online (Sandbox Code Playgroud)

MSa*_*ers 17

最容易理解为什么这是非法的原因是考虑vtable.当然,这只是一个常见的实现,其他的是允许的.但是virtualC++中的所有函数都设计为可以使用vtable实现.

现在,有多少项是那里的vtableCFoo<int>?有条目doSomething<float>吗?而且doSomething<float*>?而且doSomething<float**>?这些模板允许生成无限的函数集.通常这没问题,因为你只使用有限的子集,但对于虚函数,这个子集是未知的,因此vtable需要是无限的.

现在,您可能真的只想在vtable中输入一个条目.在这种情况下,您可以按如下方式编写:

template < class FOO_TYPE, class BAR_TYPE>
class CFoo{
    public:
        ...
        virtual void doSomething( const CBar<BAR_TYPE> &); // now OK.
        ...
        virtual ~CFoo();
    protected:
        MyClass < FOO_TYPE > * m_pClass;
};
Run Code Online (Sandbox Code Playgroud)

这意味着vtable for CFoo<int, float>将有一个条目for doSomething(float const&).

  • @ v.oddou:不现实.链接器必须匹配所有可能的基类的所有虚拟调用,并实例化模板.然后需要编译那些实例化.这些新的实例化反过来可能包含新的虚拟调用,因此这个过程必须是迭代的. (3认同)

Nim*_*Nim 5

如果您确实需要使此方法成为虚拟方法,请考虑使其成为CBar<>多态并传递未模板化的基本类型。

编辑:像这样:

// non-templated base class
class BarBase
{
 // common methods go here..
};

template <typename BAR_TYPE>
class CBar : public BarBase
{
 // implement methods from BarBase ...
};

template < class FOO_TYPE>
class CFoo{
    public:
        ...
        // now we take the base type, and this method does not need to be a template
        virtual void doSomething( BarBase const* ptrBar );
        ...
        virtual ~CFoo();
    protected:
        MyClass < FOO_TYPE > * m_pClass;
};

template < class FOO_TYPE >
void CFoo<FOO_TYPE>::doSomething( BarBase const* ptrBar ){
..
}
Run Code Online (Sandbox Code Playgroud)