Как можно исхитриться сделав преобразование типа функции допустим:
int (class_a::)( int, void *) в int (*)(int, void *)
чтобы впоследствие сделать присвоение указателя функции к переменной последнего типа.
Здравствуйте, Аноним, Вы писали:
А>Как можно исхитриться сделав преобразование типа функции допустим:
А>А>int (class_a::)( int, void *) в int (*)(int, void *)
А>
А>чтобы впоследствие сделать присвоение указателя функции к переменной последнего типа.
Такое преобразование невозможно. Расскажи подробнее, зачем тебе это понадобилось. Возможно, тебе поможет связка
boost.bind + boost.function.
Здравствуйте, Аноним, Вы писали:
А>Как можно исхитриться сделав преобразование типа функции допустим:
А>А>int (class_a::)( int, void *) в int (*)(int, void *)
А>
А>чтобы впоследствие сделать присвоение указателя функции к переменной последнего типа.
Указатель на метод в указатель на функцию преобразовать нельзя. Для этого обычно пишут классы — адаптеры, а потом — функции-обертки.
Здравствуйте, Аноним, Вы писали:
А>Как можно исхитриться сделав преобразование типа функции допустим:
А>А>int (class_a::)( int, void *) в int (*)(int, void *)
А>
А>чтобы впоследствие сделать присвоение указателя функции к переменной последнего типа.
Тема, конечно, избитая донельзя, ну давай еще раз. Все нестатические функции-члены один имеют неявный параметр — указатель на объект для которого этот метод вызван. Когда мы пишем:
my_object->some_foo(), на самом деле мы неявно вызываем функцию с одним параметром, а не с пустым списком параметров, как это может показаться при поверхностном взгляде. В данном случае этим параметром будет указатель
my_object, который внутри функции
some_foo() будет доступен как
this.
Кроме списка параметров для функций, как свободных, так и функций-членов, существенен протокол вызова. Для свободных функций это может быть
__cdecl,
__stdcall или
__fastcall. Для функций-членов допустимы все вышеперечисленные протоколы вызова плюс еще один —
__thiscall, который используется по умолчанию. К чему я все это? К тому, что если мы собираемся заняться реинтерпретацией типов указателей на функции, то не учитывать протокол вызова нельзя.
Итак, пусть имеется некий класс
A, в котором объявлена функция-член
foo.
class A
{
public:
int foo(int, void*);
};
Для MSVC при стандартных настройках объявление функции
foo может быть интерпретировано как объявление обычной функции следующего вида:
int __thiscall foo(A*, int, void*);
Но тут одна проблема: мы не можем использовать
__thiscall для свободных функций. Но зато мы можем изменить протокол вызова функции-члена:
class A
{
public:
int__cdecl foo(int, void*);
};
Вот теперь можно заняться грязными хаками:
typedef int Handler(A*, int, void*); //Подразумевается, что по умолчанию протокол __cdecl
Handler* f = reinterpret_cast<Handler*>(&A::foo);
A a;
f(&a, 123, 0);
Существует более легальный способ преобразования функциональных объектов при с использованием
boost::function,
boost::bind,
boost::mem_fn и иже с ними. По возможности, нужно стараться использовать именно эту технику во избежание разного рода неприятностей. Единственное ограничение этого подхода, это то, что в результате такого преобразования мы получаем функциональный объект, а не указатель на функцию. И если по специфике задачи нужен именно указатель а не функционал, то тут два пути: либо пускаться во все тяжкие, либо перепроектировать.