Статические "виртуальные" методы
От: theven Россия  
Дата: 23.11.12 10:20
Оценка:
Решал тут свои задачи, натолкнулся на способ создавать как-бы виртуальные функции при статическом полиморфизме. Я такого метода не встречал, возможно он где-то описан, но я поделюсь тут, может кому пригодится.

И так. Методика применима к иерархии шаблонных классов. В общем-то это менее громоздкая альтернатива стратегиям. Допустим имеется базовый шаблонный класс который капитулирует какие-то алгоритмы.
template <typename T>
struct Base
{
  
    void algorithm()
    {
        std::cout << "doSomething: ";
        doSomething();
        std::cout << std::endl;
    }

    inline void doSomething() { std::cout << "1"; };

};


Нам нужно написать один или несколько производных классов у которых изменяется функциональность только doSomething(), в полиморфной иерархии мы бы объявили этот метод виртуальным, но мы делаем набор библиотечных базовых или конечных классов с различной функциональностью и не хотим использовать виртуальность, к тому же хотим встраивания doSomething(). Для этого добавляем в иерархию дополнительный шаблонный параметр — тип конечного класса. И вызываем из него наши "статические виртуальные методы".


template <typename T, typename EndClassType>
struct Base
{
  
    void algorithm()
    {
        std::cout << "doSomething: ";
        static_cast<EndClassType*>(this)->doSomething();
        std::cout << std::endl;
    }

    // "статическая виртуальная функция" (со встраиванием)
    inline void doSomething() { std::cout << "1"; };

};

template <typename T, typename EndClassType>
struct Derived: public Base<T, EndClassType>
{
    // переопределяем doSomething с другим поведением
    inline void doSomething() { std::cout << "2"; };
};



template <typename T>
struct EndClass1: public Base<T, EndClass1<T>>
{
    // не переопределяет doSomething
};

template <typename T>
struct EndClass2: public Derived<T, EndClass2<T>>
{
    // не переопределяет doSomething
};

template <typename T>
struct EndClass3: public Base<T, EndClass3<T>>
{
    // переопределяем doSomething с третьим поведением
    inline void doSomething() { std::cout << "3"; };
};

template <typename T>
struct EndClass4: public Derived<T, EndClass4<T>>
{
    // переопределяем doSomething с четвертым поведением
    inline void doSomething() { std::cout << "4"; };
};


int main()
{
    EndClass1<int> c1; c1.algorithm();
    EndClass2<int> c2; c2.algorithm();
    EndClass3<int> c3; c3.algorithm();
    EndClass4<int> c4; c4.algorithm();
}
Re: CRTP
От: Qbit86 Кипр
Дата: 23.11.12 10:24
Оценка: +1
Здравствуйте, theven, Вы писали:

T>Решал тут свои задачи, натолкнулся на способ создавать как-бы виртуальные функции при статическом полиморфизме. Я такого метода не встречал, возможно он где-то описан, но я поделюсь тут, может кому пригодится.

T>Нам нужно написать один или несколько производных классов у которых изменяется функциональность только doSomething(), в полиморфной иерархии мы бы объявили этот метод виртуальным, но мы делаем набор библиотечных базовых или конечных классов с различной функциональностью и не хотим использовать виртуальность, к тому же хотим встраивания doSomething(). Для этого добавляем в иерархию дополнительный шаблонный параметр — тип конечного класса. И вызываем из него наши "статические виртуальные методы".

CRTP
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: CRTP
От: theven Россия  
Дата: 23.11.12 10:31
Оценка: 1 (1) :))
Здравствуйте, Qbit86, Вы писали:
Q>CRTP
Ну ясно Как обычно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.