Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатель на функцию. 
:(
    Опции темы
nikakoi
Дата 28.6.2006, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 6.5.2006

Репутация: нет
Всего: нет



Доброго всем утра.
Расскажите плз, что такое указатель на функцию... и желательно с примером..
Ато все, что я в инете нашел слишком непонятноsmile 
PM MAIL   Вверх
586
Дата 28.6.2006, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Это адрес на какую-либо область кода.
Указатель на функцию возвращает, например, функция GetProcAddress.
Любая функция, по сути, является адресом, только имеет ещё и параметры.

Код
FARPROC p;     // указатель на ф-цию
int (__stdcall *MsgBoxA)(HWND, char*, char*, int);     // сама ф-ция (переменая)

p=GetProcAddress(GetModuleHandle("user32"), "MessageBoxA");
MsgBoxA=(int (__stdcall *)(HWND, char*, char*, int))p;     // приведение указателя к ф-ции
MsgBoxA(hWnd, "Hello world", "Caption", 64);                // использование ф-ции
  

Это сообщение отредактировал(а) 586 - 28.6.2006, 10:58
PM   Вверх
BreakPointMAN
Дата 28.6.2006, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 15.9.2004
Где: Saratov

Репутация: 14
Всего: 24



nikakoi, почему ты считаешь, что мы расскажем тебе понятнее? 


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
nikakoi
Дата 28.6.2006, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 6.5.2006

Репутация: нет
Всего: нет



Ну здесь по крайней мере я могу попросить рассказать понятнее..
А в литературе никому и не пожалуешься 
PM MAIL   Вверх
slava72
Дата 28.6.2006, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 23.6.2006

Репутация: 1
Всего: 1



Код


bool g(int,int); // Обявляем 1-ю функцию
bool f(int, int); // Обявляем 2-ю функцию
...
typedef bool (*Func)(int,int); // Func- указатель на функцию типа g

bool Comp5(int p1, Func func) { // функция принимающая указатель на функцию в кач. параметра
  return func(p1, 5);
}

Func pF = g; // инициализируем указатель на функцию функцией g
Comp5(7, pF); //фактически g(7,5)
pF= f;
Comp5(3, pF); //фактически f(7,5)




Вариантов использования - вагон и маленькая тележка ;))
Например - хранение в члене класса, и вызов соответствующей функции (можно назвать суперполиморфизм ))

массив уазателей на функцию для замены switch

Организация "фабрики классов" - список пар <ключ (например строка),  функция создания объекта>
Соответственно можно динамически создавать  объект нужно класса, по ключу не известному в момент компиляции и т.д.


 
PM MAIL   Вверх
bilbobagginz
Дата 28.6.2006, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: 3
Всего: 317



в контексте C

указатель на ф-ю - это переменная, содержащая адрес функции типа описанного в объявлении этой переменной. позволяет напр, под одним именем скрывать вызов нескольких функций похожего вида(1), или осуществлять callback.

0) объявление и инициализация:
Код

/** объявление */
/******************************************/
int (*func_ptr)(int,int); /** объявление указателя на функцию вида int foo1(int x, int y) */
void (*func_ptr)(void); /** объявление указателя на функцию вида void foo2() */
int (*func_table[20])(float); /** объявления "таблицы" функций вида int foo(float) */
/** инициализация */
/******************************************/
void (*print_element)(type,elm_ptr*)=print_int;
/** данный, вышенаписанный код создает переменную print_element, и инициализирует её 
на вызов обыкновенной функции print_int(type t,elm_ptr* elm)
если мы хотим возпользоваться переменной - вызвать функцию на которую она указывает - пишем:
res=print_elm(t,elm);
и на самом деле это еквивалентно вызову:
res=print_print_int(t,elm);
*/
typedef enum BOOL { FALSE =0, TRUE = 1 } BOOL;
typedef enum TYPE { FLT=0,INT=1,DBL=2,CPX=3,TDP=4,ERR=5} TYPE;
typedef struct{
   TYPE t;
   union {
       int id;
       float fd;
       double dd;
       complex cxd;
       r3vector r3d;
   } data;
} element;

BOOL compare_int(int*,int*);
BOOL compare_float(float*,float*);
BOOL compare_double(double*,double*);
BOOL compare_cmplx(complex*,complex*);
BOOL compare_3dpoint(r3vector*,r3vector*);
BOOL compare_err(void*,void*);



BOOL (*sravni[6])(void*,void*)={
compare_int,
compare_float,
compare_double,
compare_cmplx,
compare_3dpoint,
compare_err
};

int set_index(TYPE t){
      if (t>=0&&t<=5) return t;
      else return 5;
}

/** здесь не хватает инициализирующего кода, но в результате: */
element e1,e2;
e1.t=INT;e1.data=(int)8;
e2.t=INT;e2.data=(int)9;

if (sravni[set_index(e1.t)](&e1.data,&e2.data)){
/** обратим внимание на вызов set_index, для определения индекса в "таблице функций" */
    printf("left is bigger than right\n");
}
else 
    printf("left is not bigger than right\n");


т.е. в конце вызывается функция compare_int, a в блок if,else можно также засунуть любую 
переменную вида element, несмотря на факт что data может быть совершенно разных видов. 
это также используется для замены switch на 1 вызов массива указателей на функции 
про callback писАть не буду, потому, что колбэк это то же самое, просто когда функции compare_* 
пишутся в другом модуле, и тот модуль может быть более низкого/высокого уровня абтракции, а также 
может быть написан другой командой.

надеюсь не запутал.
пока.
   

Это сообщение отредактировал(а) bilbobagginz - 28.6.2006, 11:36


--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
nikakoi
Дата 28.6.2006, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 6.5.2006

Репутация: нет
Всего: нет



smile Спасибо=)
Кажется начал понимать.. 
PM MAIL   Вверх
Xenon
Дата 28.6.2006, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



А зачем оно надо, скажите мне? smile 


--------------------
user posted image  
PM MAIL   Вверх
MAKCim
Дата 28.6.2006, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

А зачем оно надо, скажите мне? 

примеров очень много
главное - оно точно надо  smile  
первое, что в голову пришло
Код

class object;

class creator
{
private:
...
    typedef object* (*function_t)();
    typedef map<string,function_t> map_t;
...
private:
    map_t map_;
public:
    void add(const string& name, fucntion_t function)
        { map_[name]=function; }

    object* create(const string& name)
        { return map_[name](); }
...
};

реализации интерфейса object могут быть в другом месте и creator о них не знает, а знают функции создания
с сигнатурой
object* () 

Это сообщение отредактировал(а) MAKCim - 28.6.2006, 13:35


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Ryn
Дата 28.6.2006, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 21.4.2006

Репутация: нет
Всего: нет



а если мне нужен указатель на функцию, находящуюся в классе ? 
PM MAIL   Вверх
Void
Дата 28.6.2006, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Ryn, такие указатели тоже есть, но они не привязаны к конкретному экземпляру класса. Чтобы вызвать метод через указатель на него, нужен сам указатель и объект.
Код
#include <iostream>

class A {
public:
    void foo(int x) {
        std::cout << "foo(" << x << ") called\n";
    }
};

typedef void (A::*memfunptr)(int);

int main() {
    memfunptr foop = &A::foo;
    A a, *b = new A;
    (a.*foop)(1);
    (b->*foop)(2);
    delete b;
}

Если нужна привзяка к конкретному экземпляру, используются специальные объекты-функцторы. См. Boost.Function и Boost.Bind. 


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Ryn
Дата 28.6.2006, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 21.4.2006

Репутация: нет
Всего: нет



спасибо 
PM MAIL   Вверх
AlanG
Дата 29.6.2006, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 11.5.2006
Где: РашЫн ФидирейшЫн

Репутация: нет
Всего: нет



Я извиняюсь, если не в тему спрошу, но у меня возникли непонятки с типами указателей, когда имя указателя становится новым типом.
Например:
Код

typedef int (*ff1) (int, char); //Указатель на функцию, которая принимает два аргумента, int и char
ff1 massiv[]={&ch1, &ch2, &ch3}; //Массив ссылок на функции с типом ff1


Получается тип указателя на функцию, предполагает указатель на функцию которая принимает и возвращает теже типы данных, что и указатель на функцию который и установил новый тип (ff1 в данном случае). 

Просьба прокоментировать вышеизложенное.



 
PM MAIL   Вверх
MAKCim
Дата 29.6.2006, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



AlanG
а что тебе не нравится?
ты определил синоним типа int (*)(int,char), назвал его ff1, и далее создал массив из элементов этого типа, в данном случае из указателей на функции 
твой код аналогичен слудующему
Код

...
int (*massiv[])(int, char)={&ch1,&ch2,&ch3};
...
 

Это сообщение отредактировал(а) MAKCim - 29.6.2006, 11:04


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
slava72
Дата 29.6.2006, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 23.6.2006

Репутация: 1
Всего: 1



AlanG,
Это не "Массив ссылок на функции с типом ff1", а массив указателей на функцию типа ff1.

для функции выражения &func и func - это одно и тоже

Ryn, 
Одно уточнение - статические функции класса - это обычные функции, а не члены класса, т.е.
их можно использовать в контексте обычных указателей на функцию. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1084 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.