вопрос относительно шаблонизации виртуальной функции - PullRequest
1 голос
/ 25 марта 2010

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

У меня есть класс под названием System:

#include "Vector.h"
class System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0)      const  = 0;  
};

class UnresolvedSystem : public System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const
    {
      //do something 
    }  
};

В Vector.h:

tenplate<typename T>
class Vector
{
  //some functions
};

Теперь я хочу шаблонизировать VectorToLocal в system.h, чтобы взять только Vector<T>, но я не могу этого сделать, поскольку это виртуальная функция. Я хочу обходной путь. Я знаю, что могу иметь VectorToLocal принимать Vector<float>, Vector<double> и т. Д. В качестве аргументов, но я не хочу этого делать.

Ответы [ 6 ]

2 голосов
/ 25 марта 2010

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

Но виртуальные функции-члены могут принимать полностью определенные типы, которые просто используют шаблоны:

class System
{
public:
    virtual void DoIt(vector<int>* v);
};


int main()
{
    vector<int> v;
    System s;
    s.DoIt(&v);
    return 0;
}

Кстати, почему вы реализуете свой собственный векторный класс?

1 голос
/ 26 марта 2010

Любой из распространенных способов устранения виртуальных функций, например CRTP, также поможет.

0 голосов
/ 26 марта 2010

Если вы хотите предоставить единственную точку реализации, то можете переадресовать вызов в шаблон

struct base {
   virtual void f( int );
   virtual void f( double );
};

struct derived : base {
   virtual void f( int x ) { f_tmpl(x); }
   virtual void f( double x ) { f_tmpl(x); }

   template <typename T>
   void f_tmpl( T x ) { // ... }
};

Могу поспорить, что с помощью списка типов вы могли бы фактически генерировать виртуальные функции, но это, вероятно, простоусложнить код.

0 голосов
/ 26 марта 2010

У вас есть несколько вариантов, все в зависимости от того, что вы пытаетесь сделать.

Если T каким-то образом присущ System (например, если System имеет переменные-члены типа T), вы можете сделать весь класс шаблонным для него:

template< typename T >
class System
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0)      const  = 0;  
};

template< typename T >
class UnresolvedSystem : public System<T>
{
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const
    {
      //do something 
    }  
};

Если контекст T является локальным только для VectorToLocal, то лучшим решением при проектировании было бы выделение функции вне класса:

template< typename T >
void VectorToLocal( System& s, Vector<T>& global_dir, ... )
{
   // use s's public interface to make changes to the object
}

Можете ли вы предоставить более подробную информацию о цели VectorToLocal?

0 голосов
/ 26 марта 2010

Если вы определяете шаблонную функцию C ++, для каждой комбинации типов аргументов шаблона создается новая реализация функции. Таким образом, одна функция в исходном коде может быть одной или несколькими функциями в машинном коде. Вот что помогает сделать их быстрыми.

Теперь компилятор определяет, какие версии вашей функции следует генерировать, как она вызывается. Если int никогда не является параметром типа, компилятор не должен генерировать реализацию. Теперь, если вы делаете виртуальный вызов, становится трудно выяснить, как он используется, и может случиться так, что определение функции отсутствует в заголовочном файле при компиляции функции, которая использует функцию шаблона. Без исходного кода функции компилятор не может создать скомпилированную функцию.

Есть несколько других недостатков, с которыми вы сталкиваетесь, когда C ++ разрешает виртуальные функции шаблонов. Например, как обычно реализуются виртуальные функции.

И это, вероятно, причина того, что C ++ не позволяет этого. Вы можете подумать, что вам это нужно, но, возможно, есть другой способ, который, я уверен, люди помогут вам найти, если вы дадите нам немного больше подробностей о требованиях этого фрагмента кода.

0 голосов
/ 25 марта 2010

Я не знаю, что вы хотите сделать с вашим вектором, но иногда можно сделать так, чтобы функция шаблона вызывала виртуальную функцию, которая реализует реальное поведение. В этом случае вы реализуете шаблон-версию в своем суперклассе и заставляете его вызывать там не-шаблон чисто виртуальный, который делает все, что вы хотите. Обычно это работает, только если вы наложили ограничение на параметр типа:

#include "Vector.h"
class System
{
    virtual void print( const std::string & ) const = 0;
    template<class T>
    void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos =  0) const {
        print( T.GetName() );
    }
};

class UnresolvedSystem : public System
{
    virtual void print( const std::string & Name ) const {
        std::cout << name << std::endl;
    }  
};

В этом случае я предположил, что T имеет функцию-член GetName.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...