шаблоны — C ++ несколько функций-членов обратного вызова из разных классов без std и boost

Я новичок в C ++ и не хочу использовать какие-либо библиотеки, потому что хочу по-настоящему понять, что происходит внутри.
Кроме того, я стараюсь как можно меньше использовать библиотеку (для повышения производительности и), чтобы сделать ее максимально независимой от платформы (без экспорта библиотеки).
В общем, я бы не хотел использовать std или boost для решения этой проблемы.

Мой вопрос:

У меня есть EventHandler, который имеет функцию:

template<class T> void EventHandler::SetCallbackFunction(T* obj, void (T::*mem_fkt)(void));

Я должен сохранить объект и функцию, чтобы вызвать его позже.
Есть 2 возможности:

  • EventHandler как класс шаблона (и typedef)
  • void * -> но для вызова функции мне нужно привести ее обратно и для этого мне нужно имя класса: /

Почему они не работают:
— EventHandler не может быть классом шаблона, потому что он должен обрабатывать несколько классов.
— void * -> Я не знаю, как сохранить имя класса, чтобы привести его позже

Как я могу это сделать?
(Или есть другой способ? Может быть, способ сохранить имя класса для последующего приведения?)

РЕДАКТИРОВАТЬ:
Кроме того, мне может понадобиться зарегистрировать несколько функций обратного вызова для каждого класса, так что интерфейс на самом деле не вариант.

class A {
public:
void CallbackFktForEventHandler();
void CallbackFktForAnimationHandler();
etc...
};

И я знаю, что вы могли бы решить это на основе чего-то вроде этого:

class A{
public:
void Callback();
static void CallbackStatic(void* self){
static_cast<A*>->CallBack();
};
};

Но это слишком сильно ограничивает меня на мой вкус.

3

Решение

Вы можете попробовать это:

Создайте (чисто виртуальный) базовый класс, который имеет только одну функцию call():

class Function{
virtual void call()=0;
}

Создайте шаблонный класс, который хранит указатель на функцию и объект и наследует его от Function

template<typename T>
class TemplatedFunction{
void (T::*m_fkt)(void);
T* m_obj;

TemplatedFunction(T* obj, void (T::*fkt)(void)):m_fkt(fkt),m_obj(obj){}

void call{
(m_obj->*m_fkt)();
}
}

А затем хранить указатели на Function в вашем Event-Handler и просто использовать Function->call()

Попробуйте онлайн: http://ideone.com/3Hu5pw

Но вы сделаете свою жизнь намного проще, если будете использовать хотя бы стандартную библиотеку. По сути, я бы использовал std :: bind, чтобы связать ваш объект и функцию-член вместе с функцией void () (void), а затем сохранить эти объекты внутри std :: vector.

Редактировать: Окталист был быстрее;)

4

Другие решения

Ты можешь использовать стирание типа. Вы эффективно сохраните тип obj путем создания шаблона класса, который реализует не шаблонный виртуальный интерфейс. Это по сути как std::function реализован, поэтому вы просто пишете свою собственную базовую версию std::function,

struct ICallback
{
virtual void call() = 0;
};

template <class T>
struct Callback : public ICallback
{
virtual void call() override { (m_obj->*m_func)(); }
Callback(T *obj, void (T::*func)()) : m_obj(obj), m_func(func) {}
T *m_obj;
void (T::*m_func)();
};

template <class T>
std::unique_ptr<ICallback> wrap(T *obj, void (T::*func)())
{
return std::make_unique<Callback<T>>(obj, func);
}

Если вы не хотите использовать std::unique_ptr Вы можете бросить свой собственный или использовать злой сырой указатель владения.

2

По вопросам рекламы [email protected]