Обойти то, что невозможно сделать шаблоны функций виртуальными? - PullRequest
1 голос
/ 23 июня 2010

У меня есть вершина абстрактного класса, которая представляет собой n-кортеж.Элемент вершины может быть любого типа: т.е. компоненты вершины могут иметь тип int, int, float или что-то еще.Поскольку у вершины может быть произвольное число измерений, я думал о том, чтобы у класса был набор компонентов, подобный так:

class vertex {
    public:
        template <class T>
        virtual void setComp(int componentnumber, T value) = 0;
};

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

Спасибо.

Ответы [ 5 ]

2 голосов
/ 23 июня 2010

Ну, как правило, вы должны иметь тип вершины в качестве параметра шаблона, чтобы он мог храниться правильно:

template<typename T, size_t NumAxes = 3>
class vertex {
    private:
        T comp[NumAxes];
};

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

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value) { comp[index] = static_cast<T>(value); }
private:
    T comp[NumAxes];
};

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

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value)
    { _setComp(index, static_cast<T>(value)); }
protected:
    T comp[NumAxes];
    virtual void _setComp(size_t index, T value) 
    { comp[index] = value; }
};

template<typename T, size_t NumAxes = 3>
class logged_vertex: public vertex<T, NumAxes> {
protected:
    virtual void _setComp(size_t index, T value);
};

template<typename T, size_t NumAxes = 3>
void logged_vertex<T, NumAxes>::_setComp(size_t index, T value)
{   cout << "Index " << index << " changed from " << comp[index];
    vertex<T, NumAxes>::_setComp(index, value);
    cout << " to " << comp[index] << endl;
}
0 голосов
/ 23 июня 2010

Прежде всего, я бы спросил себя, действительно ли вам нужен полиморфный доступ к объектам вершин во время выполнения. Например, если вам нужно иметь список объектов вершин * разных типов (double, int и т. Д.) И получать к ним полиморфный доступ.

Мне кажется, что вершина - это типичный случай полиморфизма во время компиляции (то есть шаблон template <typename CoordinateType> class vertex;).

0 голосов
/ 23 июня 2010

Используйте полиморфизм вместо шаблонов.

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

Реализация этих решений будет включать boost :: any или boost :: option, чтобы сэкономить ваше время.

0 голосов
/ 23 июня 2010

Because the vertex can have an arbitrary number of dimensions - а не сделать это

template<size_t N> class vector {

   private:
     boost::any elems[N];
}

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

virtual void setComp(int, float) = 0;
virtual void setComp(int, bool) = 0;
0 голосов
/ 23 июня 2010

Это очень странное сочетание ОО и общего программирования.Я думаю, вам следует выбрать один или другой.

Сделать класс вершин шаблоном или , определить базовый класс для параметра 'value' и получить классы обработчиков пользовательских типов.

...