Я новичок в C ++ и не хочу использовать какие-либо библиотеки, потому что хочу по-настоящему понять, что происходит внутри.
Кроме того, я стараюсь как можно меньше использовать библиотеку (для повышения производительности и), чтобы сделать ее максимально независимой от платформы (без экспорта библиотеки).
В общем, я бы не хотел использовать std или boost для решения этой проблемы.
Мой вопрос:
У меня есть EventHandler, который имеет функцию:
template<class T> void EventHandler::SetCallbackFunction(T* obj, void (T::*mem_fkt)(void));
Я должен сохранить объект и функцию, чтобы вызвать его позже.
Есть 2 возможности:
Почему они не работают:
— EventHandler не может быть классом шаблона, потому что он должен обрабатывать несколько классов.
— void * -> Я не знаю, как сохранить имя класса, чтобы привести его позже
Как я могу это сделать?
(Или есть другой способ? Может быть, способ сохранить имя класса для последующего приведения?)
РЕДАКТИРОВАТЬ:
Кроме того, мне может понадобиться зарегистрировать несколько функций обратного вызова для каждого класса, так что интерфейс на самом деле не вариант.
class A {
public:
void CallbackFktForEventHandler();
void CallbackFktForAnimationHandler();
etc...
};
И я знаю, что вы могли бы решить это на основе чего-то вроде этого:
class A{
public:
void Callback();
static void CallbackStatic(void* self){
static_cast<A*>->CallBack();
};
};
Но это слишком сильно ограничивает меня на мой вкус.
Вы можете попробовать это:
Создайте (чисто виртуальный) базовый класс, который имеет только одну функцию 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.
Редактировать: Окталист был быстрее;)
Ты можешь использовать стирание типа. Вы эффективно сохраните тип 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
Вы можете бросить свой собственный или использовать злой сырой указатель владения.