шаблоны не могут быть «виртуальными» - PullRequest
13 голосов
/ 10 февраля 2011

Учитывая приведенный ниже код, компилятор показывает сообщение, указывающее, что error: templates may not be ‘virtual’.У кого-нибудь есть предложения по устранению ошибки?

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 ){
    ...
}

Ответы [ 4 ]

17 голосов
/ 11 февраля 2011

Самая простая причина понять, почему это незаконно, - рассмотреть vtable.Конечно, это только одна общая реализация, и другие разрешены.Но все функции virtual в C ++ разработаны таким образом, что их можно реализовать с помощью vtable.

Теперь, сколько записей в vtable из CFoo<int>?Есть ли запись для doSomething<float>doSomething<float*>doSomething<float**>?Подобные шаблоны позволяют генерировать бесконечный набор функций.Обычно это не проблема, так как вы используете только конечное подмножество, но для виртуальных функций это подмножество неизвестно, и поэтому виртуальная таблица должна быть бесконечной.

Теперь, возможно, вы действительно хотели толькоодиночная запись в 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;
};

Это означает, что в vtable для CFoo<int, float> будет одна запись для doSomething(float const&).

2 голосов
/ 10 февраля 2011

Вы можете использовать то, что мы называем в Symbian как «шаблон дизайна шаблона».Вот пример кода, чтобы дать вам представление:

class Base {
public:
        virtual int DoSomething() = 0;
protected:
        Base();
};

class IntermediateBase : public Base {
protected:
        IntermediateBase(void* aSomeParam, void* aArg)
        : iSomeParam(aSomeParam)
        , iArgs(aArg) 
        {}

        virtual int DoSomething() = 0;
protected:
        void* iSomeParam;
        void* iArgs;
};

template <class TYPE, class INPUT>
class ConcreteClass : public IntermediateBase {
        typedef int (TYPE::*MemberFuncPtr)(const INPUT&);
public:
        ConcreteClass(TYPE& aCommandType, 
                      INPUT& aArgumentsToCommand,
                      MemberFuncPtr aMFP)
        : IntermediateBase(static_cast<TYPE*>(&aCommandType),
                           static_cast<INPUT*>(&aArgumentsToCommand) )
        , iMFP(aMFP)
        {}

        virtual int DoSomething()  // VIRTUAL AND INLINE Note - dont make it 
                                   // virtual and inline in production if 
                                   // possible to avoid out-of-line copy   
        {
            return static_cast<TYPE*>(iSomeParam)->*ConcreteClass::iMFP)
                           (*(static_cast<INPUT*>(iArgs));
        }
private:
        MemberFuncPtr iMFP;
}; 
1 голос
/ 10 февраля 2011

Если вам действительно нужно сделать этот метод виртуальным, рассмотрите возможность сделать 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 ){
..
}
1 голос
/ 10 февраля 2011

Ну, сообщение об ошибке довольно ясно. Шаблоны функций-членов не могут быть виртуальными . Как решить эту проблему, зависит от вашей проблемы, но проще всего было бы сделать функции-члены не виртуальными и пересмотреть ваш дизайн.

...