2013-07-24 3 views
4

У меня есть базовый класс с несколькими чистыми виртуальными методами, например.Как вызвать шаблонный метод в производном классе, который реализует чистый виртуальный метод в базовом классе?

class GenericFunction 
{ 
public: 
    GenericFunction() { /* Init generic function state */ }; 
    virtual void Iterate(short *ps, unsigned cs) = 0; 
    virtual void Iterate(float *ps, unsigned cs) = 0; 
} 

Тогда у меня есть куча производных классов, реализующих определенные функции, и я хочу, чтобы вызвать метод Iterate() на сборе этих функций, предоставляя каждому из них блок выборок данных. Я знаю только тип данных в тот момент, когда я звоню Iterate().

Методы Iterate() почти одинаковы для многих функций, поэтому я хотел бы использовать шаблон. Я не могу использовать шаблон в базовом классе, потому что виртуальные шаблоны не разрешены. Чтобы получить компилятор генерировать правильные методы из шаблона, я обнаружил, что я должен использовать косвенный вызов шаблон следующим образом:

class SpecificFunction : GenericFunction 
{ 
public: 
    SpecificFunction() : GenericFunction() { /* Init specific function state */ }; 

    template<class T> void IterateT(T *ps, unsigned cs) { 
    // Do function operations on block of samples 
    }; 
    virtual void Iterate(short *ps, unsigned cs) { IterateT(ps, cs); }; 
    virtual void Iterate(float *ps, unsigned cs) { IterateT(ps, cs); }; 
} 

Я не хочу, чтобы весь класс для SpecificFunction качестве шаблона потому что существует много других методов, и весь этот код не зависит от типа используемых образцов. Я не хочу, чтобы весь этот код был реплицирован, когда он генерируется из шаблона, потому что он работает во встроенном процессоре, а кодовое пространство ограничено.

Это кажется запутанным и неэффективным. Есть лучший способ сделать это?

+0

В качестве опоры: не забудьте сделать базовый деструктор 'virtual'. – Nawaz

+0

Вы можете подклассы шаблонов SpecificFunction с помощью только шаблонного кода. – John

+0

Do * all * дочерние итерационные функции вызывают 'IterateT'? Или некоторые из них имеют свою собственную реализацию? –

ответ

1

Это случай, когда страшный бриллиант (виртуальное наследование и множественное наследование) может вам помочь. Вы можете использовать шаблонный прокси-класс, который наследует фактически от вашего GenericFunction, чтобы быть вашей общей реализацией. Затем используйте множественное наследование для конкретных реализаций, которые вы хотите создать SpecificFunction.

class ProxyState; 

template <typename T> 
class ProxyFunction : public virtual GenericFunction 
{ 
public: 
    ProxyFunction() : GenericFunction() {}; 
    virtual ProxyState * state() { return 0; } 
    void Iterate (T *ps, unsigned cs) { 
    // Do function operations on block of samples, using state() 
    // if necessary 
    std::cout << __PRETTY_FUNCTION__ << "\n"; 
    } 
}; 

class SpecificFunction : public ProxyFunction<short>, 
         public ProxyFunction<float> 
{ 
public: 
    SpecificFunction() : ProxyFunction<short>(), 
         ProxyFunction<float>() 
    { /* Init specific function state */ }; 
}; 

//... 
SpecificFunction s; 
GenericFunction *g = &s; 
g->Iterate((short *)0, 0); 
g->Iterate((float *)0, 0); 

выше программа дает мне следующий вывод:

void ProxyFunction<T>::Iterate(T*, unsigned int) [with T = short int] 
void ProxyFunction<T>::Iterate(T*, unsigned int) [with T = float] 

Графически диаграмма выглядит так:

  GenericFunction 
       | 
       /_\ (virtual) 
       | 
      ProxyFunction<T> 
       | 
    ____________|____________ 
    |      | 
ProxyFunction<short> ProxyFunction<float> 
    |      | 
    /_\      /_\ 
    |_______   _______| 
      |   | 
      SpecificFunction 

Поскольку GenericFunction наследуется практически, SpecificFunction имеет только один экземпляр этого даже если он наследует несколько ProxyFunction<> с.