Мне лично хотелось узнать есть ли возможность приведения типа:
C++ (Qt)
pFunc pf = (pFunc)&MyClass::function;
Ну похоже, что нет... Может это и правильно
Даже если бы и была — в результате получился не
pFunc, а что-то вроде
int (*)(const MyClass*, int). Но на деле — указатели на члены
очень сильно отличаются по своему устройству от обычных. Так что никакое подобное приведение невозможно. В принципе, возможно это обойти, но в любом случае — чтобы получить требуемый
int (*)(int) придется где-то хранить указатель на объект. С учетом этого получаем примерно такой код:
C++ (Qt)
template<class type, int (type::*fun)(int)>
class StFunc
{
static type *owner;
static int call(int i)
{
return (owner->*fun)(i);
}
public:
static pFunc get_ptr(type *t)
{
owner=t;
return &StFunc<type, fun>::call;
}
};
template<class type, int (type::*fun)(int)> type* StFunc<type, fun>::owner;
Юзать это дело так:
C++ (Qt)
MyClass m;
pFunc pm = StFunc<MyClass, &MyClass::function>::get_ptr(&m);
Главная проблема в том, что и ф-ция
call — указатель на которую мы передаем вместо требуемого — должна быть статической (чтобы это был обычный указатель на ф-цию). А значит — указатель на объект
MyClass, который она использует, тоже должен быть статическим.
Это в свою очередь означает, что одновременно мы сможем использовать только один такой указатель для каждой пары класс/метод.
Иными словами — это костыль. Очень кривой и с большим количеством потенциальных граблей. Так что единственный случай, когда такое нужно использовать — это если мы не можем никак изменить ф-цию, которая этот самый
pFunc хочет. Если же мы ее можем изменить, можно сделать гораздо проще:
Было:
C++ (Qt)
typedef int (*pFunc)(int);
int myFunction(pFunc pf)
{
int i;
// do something...
return pf(i);
}
Стало:
C++ (Qt)
template<class TFunc>
int myFunction(TFunc pf)
{
int i;
// do something...
return pf(i);
}
И все. Теперь мы можем передавать туда не только указатели на ф-ции, но и вообще все, что позволяет применить к нему
operator().
Правда, напрямую мы передавать туда указатели на члены все еще не можем: для их вызова все еще требуется указатель на сам объект. А значит — если мы не хотим писать версию
myFunction с двумя аргументами — нам все еще нужен переходник. Но теперь он будет устроен гораздо проще, а главное — мы избавились от статики, а значит и от ограничений на одновременное использование:
C++ (Qt)
template<class type>
class MemFun
{
type *owner;
int (type::*fun)(int);
public:
MemFun(type *t, int (type::*f)(int)) : owner(t), fun(f) {}
int operator()(int i)
{
return (owner->*fun)(i);
}
};
............
// using:
MyClass m;
MemFun<MyClass> pm(&m, &MyClass::function);
myFunction(pm);
А теперь можно вспомнить, что подобный функционал (причем гораздо более гибкий, чем наш самопальный
MemFun) давно уже реализован во всяких Boost и иже с ними. Собственно, именно его и предлагали использовать выше по треду...