Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Структуры, классы и указатели на функции  (Прочитано 38686 раз)
0 Пользователей и 11 Гостей смотрят эту тему.
dorador
Гость
« : 28-11-2003 09:36 » 

Никак не соображу как разрулить следующую ситуацию:
определяю структуру, содержащую указатель на функцию
Код:
typedef int CmdEntry(ULONG cmd, void *args);

typedef struct _CMD {
ULONG code;
CmdEntry *pEntry;
} CMD, *PCMD;
а затем класс, который содержит эту структуру и в котором определена эта функция
Код:
class CClass
{
CMD cmd_01;
public:
void Init();
int Cmd_01(ULONG cmd,void* args);
};
так вот на присвоение указателю имени функции-члена класса
Код:
void CClass::Init()
{
cmd_01.code = 1;
cmd_01.pEntry = Cmd_01; // РУГАЕТСЯ ЗДЕСЬ
}
компилятор ругается
и это понятно
а не понятно как определить правильно :?:
« Последнее редактирование: 23-11-2007 14:37 от Алексей1153++ » Записан
Serega
Гость
« Ответ #1 : 28-11-2003 09:44 » 

Ругается потому что функция не статическая, т.е. у нее еще один параметр (this)
Сделай статической и заработает
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 28-11-2003 09:44 » 

А почему не определил как CMD Cmd_01 ? А так похоже несовпадение типов.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
dorador
Гость
« Ответ #3 : 28-11-2003 10:03 » 

Serega,
Цитата

Сделай статической и заработает

статическая функция может работать только со статическими переменными класса - не хотелось бы накладывать такое ограничение
RXL,
Цитата

А так похоже несовпадение типов

ругается именно на это
Цитата

А почему не определил как CMD Cmd_01 ?

по-подробнее, пжлста
в смысле  - как определить-то?
Записан
ysv_
Помогающий

ua
Offline Offline

« Ответ #4 : 28-11-2003 10:07 » 

Распостранненые грабли. Нестатическая функция-член класса неявно получает еще один параметр - указатель на экземпляр класса.
Вариантов как побороть много. Все зависит от цели. Навскидку:
1) объявить функцию-метод как статическую;
2) использовать указатель на функцию-метод класса. Пример:
==========================================
typedef unsigned long ULONG;

class CClass;

typedef int (CClass::*CmdEntry)(ULONG cmd, void *args);

typedef struct _CMD {
   ULONG code;
   CmdEntry pEntry;
} CMD, *PCMD;
 

class CClass
{
   CMD cmd_01;

public:
   void Init();
   int Cmd_01(ULONG cmd,void* args) {}
};
 

void CClass::Init()
{
cmd_01.code = 1;
cmd_01.pEntry = &CClass::Cmd_01;
}
 
int main()
{
  CClass c;
  c.Init();
}
============================================
Возможны и другие, но ИМХО эти методы небезопасны (базируются на преобразовании типов).
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 28-11-2003 10:47 » 

Цитата: dorador

Цитата

А почему не определил как CMD Cmd_01 ?

по-подробнее, пжлста
в смысле  - как определить-то?



вместо:
int Cmd_01(ULONG cmd,void* args);

пиши:
CmdEntry Cmd_01;

я обычно указатели на функции так определяю:

typedef int (*CmdEntry)(ULONG cmd, void *args);
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
dorador
Гость
« Ответ #6 : 28-11-2003 10:52 » 

ysv_,
огромное спасибо - это работает
а я пробовал
 
Цитата

class CClass;

typedef int (CClass::CmdEntry)(ULONG cmd, void *args);

и компилятор ругался
use of undefined type 'CClass'
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #7 : 28-11-2003 10:57 » 

А что? как RXL посоветовал неработает? должно работать. И не забывайте отрицательный результат от ведь тоже результат. Мы учимся не только как НАДО делать, но и как НЕ НАДО делать.  Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ysv_
Помогающий

ua
Offline Offline

« Ответ #8 : 28-11-2003 11:02 » 

Я рад Улыбаюсь
Записан
dorador
Гость
« Ответ #9 : 28-11-2003 11:23 » 

Джон,
Цитата

как RXL посоветовал неработает?

неа
как ysv_ посоветовал,  работает
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #10 : 28-11-2003 11:49 » 

Хм... у тебя какя система? под VS 6 на w2k это работает. :?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 28-11-2003 11:50 » 

Цитата: dorador
Цитата

А почему не определил как CMD Cmd_01 ?

по-подробнее, пжлста
в смысле  - как определить-то?
Извиняюсь - потропился с ответом - неподумал.
Не знаю как на это реагирует VC, а gcc гоаорит следующее:
Цитата
ISO C++ forbids taking the address of a bound member function to form a pointer to member function
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 28-11-2003 11:57 » 

Ща проверю
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #13 : 28-11-2003 12:14 » 

Код:
typedef int (*CmdEntry)(ULONG cmd, void *args);

typedef struct _CMD
{
ULONG   code;
CmdEntry pEntry;
} CMD, *PCMD;

class CClass
{
CMD cmd_01;

public:
void Init()
{
cmd_01.code = 1;
cmd_01.pEntry = Cmd_01;
}
CmdEntry Cmd_01;
};


вот этот код компилируется на VS60+sp5 w2k+sp4 без ошибок  Жаль

Может проблема в определении типа? Указатель на функцию?
« Последнее редактирование: 23-11-2007 14:42 от Алексей1153++ » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
dorador
Гость
« Ответ #14 : 28-11-2003 12:36 » 

Джон,
а как определить саму функцию Cmd_01?
Код:
CmdEntry CClass::Cmd_01()
{
return 0;
}
ругается
Код:
int CClass::Cmd_01(ULONG cmd, void* args)
{
return 0;
}
так  тоже ругается
при одинаково
'CClass::Cmd_01' : not a function
« Последнее редактирование: 23-11-2007 14:42 от Алексей1153++ » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 28-11-2003 12:48 » 

Я делал такую фигню для динамически подгружаемых библиотек  Жаль

те в данном случае было бы:
Cmd_01 = (CmdEntry)GetProcAddress(hinstLib, "Имя функции");

а так... ща попробую
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 28-11-2003 13:53 » 

Вот-вот - самая интересная часть...
Если написать так: CmdEntry Cmd_01(что угодно) {....} , то gcc говорит что я пытаюсь возвращать ф-ию.
Если круглые скобки скобки убрать, то: ошибка перед '{'.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #17 : 28-11-2003 14:19 » 

Эпиграф: "Пусть даже объясненье вздорно, чтоб честь семьи не запятнать, он должен умереть" (х/ф "Собака на сене")

Вобчем так. Моё представление энтих вещчей, как Сашок говорил, ругайте и критикуйте!

Имя функции является указателем на неё. Те:
для
typedef int (*CmdEntry)(ULONG cmd, void *args);

можно использовать:
CmdEntry Cmd_01;

проблема с определением
в стандартной записи

<return type>  ClassName::<FunctionsName>(параметры)

 <FunctionsName> - адрес функции принадлежащеё классу. :: (scope) оператор ищет её именно там. Но мы определили её как указатель. А что мы делаем когда хотим получить значение лежащие по указателю? используем оператор *. Тогда:

int CClass::*Cmd_01(ULONG cmd, void *args)
{
   return 0;
}

соответственно вызов функции:

CClass m_c;
m_c.*Cmd_01(1,p);
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
dorador
Гость
« Ответ #18 : 28-11-2003 14:41 » 

Джон,
по твоим рассуждениям написал
Код:
class CClass;

typedef int (*CmdEntry)(ULONG cmd, void *args);

typedef struct _CMD
{
   ULONG   code;
   CmdEntry pEntry;
} CMD, *PCMD;

class CClass
{
CMD cmd_01;
public:
void Init();
CmdEntry Cmd_01;
};

void CClass::Init()
{
cmd_01.code = 1;
cmd_01.pEntry = Cmd_01;
}

int CClass::*Cmd_01(ULONG cmd, void* args)
{
return 0;
}

void main( int argc, char *argv[] )
{
CClass* pClass = new CClass;
pClass->Init();
delete pClass;
}
компилится но
   cmd_01.pEntry = Cmd_01;
присваивания не производит
« Последнее редактирование: 23-11-2007 14:44 от Алексей1153++ » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #19 : 28-11-2003 15:55 » 

Чур по голове не бить!  Ага

Я думаю, что присваивание производится. А как ты собираешься это использовать?
Что-то сильно наворочено. Зачем надо где-то сохранять указатель на функцию? Что бы потом с ним что? Насколько я понял можно сделать только одну функцию такого типа. Не мог бы ты поподробнее об условии рассказать?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Serega
Гость
« Ответ #20 : 28-11-2003 22:02 » 

Насколько я понял было просто интересно поэкспериментировать с указателями на функции
А вообще подобные проблемы решаются с помощью интерфейсов
Записан
Anonymous
Гость
« Ответ #21 : 28-11-2003 22:12 » 

dorador, я пока на выходных до понедельника. В понедельник появлюсь.

Serega, честно говоря я так и не придумал как можно использовать указатель на функцию сохранённую таким способом. Я их (указатели на функции) испоьзую только при динамически подгружаемых библиотеках. Но поэкспериментировать всегда интересно - если время есть. Ага

Джон
Записан
Anonymous
Гость
« Ответ #22 : 01-12-2003 06:46 » 

Цитата

typedef int (*CmdEntry)(ULONG cmd, void *args);

typedef struct _CMD
{
   ULONG   code;
   CmdEntry pEntry;
} CMD, *PCMD;

class CClass
{
   CMD cmd_01;

public:
   void Init()
   {
      cmd_01.code = 1;
      cmd_01.pEntry = Cmd_01;
   }
   CmdEntry Cmd_01;
};

вот этот код компилируется на VS60+sp5 w2k+sp4 без ошибок  
Может проблема в определении типа? Указатель на функцию?


Он и должен правильно компилироваться, потому как здесь только присваивание
однотипных объктов(CmdEntry)

Цитата

а как определить саму функцию Cmd_01?
Код:

CmdEntry CClass::Cmd_01()
{
   return 0;
}
 

ругается
Код:

int CClass::Cmd_01(ULONG cmd, void* args)
{
   return 0;
}
 

так тоже ругается
при одинаково
'CClass::Cmd_01' : not a function


И правильно ругается:
Cmd_01 это переменная типа CmdEntry (указатель на функцию),
а не объявление функции, которую ты пытаешся определить


Цитата

Вобчем так. Моё представление энтих вещчей, как Сашок говорил, ругайте и критикуйте!

Имя функции является указателем на неё. Те:
для
typedef int (*CmdEntry)(ULONG cmd, void *args);

можно использовать:
CmdEntry Cmd_01;

проблема с определением
в стандартной записи

<return type> ClassName::<FunctionsName>(параметры)

<FunctionsName> - адрес функции принадлежащеё классу. :: (scope) оператор ищет её именно там. Но мы определили её как указатель. А что мы делаем когда хотим получить значение лежащие по указателю? используем оператор *. Тогда:

int CClass::*Cmd_01(ULONG cmd, void *args)
{
return 0;
}

соответственно вызов функции:

CClass m_c;
m_c.*Cmd_01(1,p);


Цитата

int CClass::*Cmd_01(ULONG cmd, void *args)
{
return 0;
}


Это не является корректным определением функции.

при такой записи -
typedef int (*CmdEntry)(ULONG cmd, void *args);
CmdEntry Cmd_01;

типом переменной Cmd_01 является int(*)(ULONG cmd, void *args);

А тип функции F в такой записи

class A
{
   int F(ULONG cmd, void *args);
};

int (A::*)(ULONG cmd, void *args)

Разница заметна ? Это разные вещи - указатель на функцию и указатель на функцию-член класса.
Невозможно их преобразование друг в друга. Даже их размер может отличаться(при множественном наследовании).

Правильный вариант - тот, который предложил ysv_
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #23 : 01-12-2003 08:38 » 

Цитата: Anonymous
Это разные вещи - указатель на функцию и указатель на функцию-член класса.


Дык с этим никто и не спорит. Я и не претендую на справедливость моих рассуждений. Обратимся к "первоисточнику"  Отлично

Цитата: MSDN Q94579 INFO: Creating a Function Pointer to a C++ Member Function


To create a pointer to a C++ class member function, specify the class name in the function pointer declaration, as follows:

   int (Sample::*ptr)();

This code declares a pointer to a member function in the Sample class that returns an integer. This function does not accept any arguments.


Просто было интересно поэкспериментировать. Ага

Цитата: Anonymous

Это не является корректным определением функции.


Может быть есть объяснение, почему, скажем так МОЙ Ага , вариант работает? Как работает компилятор в этом случае? По идее я написал то же самое. Только в другом месте. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
NetRaider
Гость
« Ответ #24 : 01-12-2003 09:18 » 

Цитата

Может быть есть объяснение, почему, скажем так МОЙ  , вариант работает? Как работает компилятор в этом случае? По идее я написал то же самое. Только в другом месте.

Цитата


int CClass::*Cmd_01(ULONG cmd, void *args)
{
return 0;
}

 
Это определение функции с именем Cmd_01(не являющейся членом класса)
и возвращающая указатель на функцию-член класса CClass, которая в свою очередь, возвращает int.
Эквивалентно:
int CClass::*   Cmd_01(ULONG cmd, void *args)
{
return 0;
}

Попробуй написать return 10;

ЗЫ: MSDN - "первоисточник"  Улыбаюсь
Записан
NetRaider
Гость
« Ответ #25 : 01-12-2003 09:36 » 

Цитата: dorador
Джон,
по твоим рассуждениям написал
Код:
class CClass;

typedef int (*CmdEntry)(ULONG cmd, void *args);

typedef struct _CMD
{
   ULONG   code;
   CmdEntry pEntry;
} CMD, *PCMD;

class CClass
{
CMD cmd_01;
public:
void Init();
CmdEntry Cmd_01;
};

void CClass::Init()
{
cmd_01.code = 1;
cmd_01.pEntry = Cmd_01;
}

int CClass::*Cmd_01(ULONG cmd, void* args)
{
return 0;
}

void main( int argc, char *argv[] )
{
CClass* pClass = new CClass;
pClass->Init();
delete pClass;
}
компилится но
   cmd_01.pEntry = Cmd_01;
присваивания не производит

Присваивание происходит, но переменная Cmd_01 не была инициализированна в конструкторе, поэтому ее значение неопределено. Значение cmd_01.pEntry до присваивания также неопределено. Здесь оказалось, что два неопределенных значения равны, поэтому, на первый взгляд, присваивание не производилось. В контексте функции Init() в выражении 'cmd_01.pEntry = Cmd_01;'
Cmd_01 - это переменная с типом CmdEntry, а не указатель на функцию, определенную как

int CClass::*Cmd_01(ULONG cmd, void* args)
{
   return 0;
}

Для использования указателя необходимо написать так:
 cmd_01.pEntry = ::Cmd_01;
Но тогда будет несоответствие типов.
« Последнее редактирование: 23-11-2007 14:45 от Алексей1153++ » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #26 : 01-12-2003 10:32 » new

NetRaider,  Класс!!! Где ты раньше был? Ну спасибо, успокоил - земля опять круглая.. Ну точно! return 0; подвёл. А 0 он-то и в Африке 0, он там только коричневый.  Дас злая шутка.

Тогда вызов int a = m_c.*Cmd_01(1,p); тоже понятен - вызывается просто Cmd_01(1,p); с каким то сумасшедшим кастингом в m_c.*  Я шокирован!
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
dorador
Гость
« Ответ #27 : 01-12-2003 11:07 » 

Джон,
Цитата

А как ты собираешься это использовать?
Что-то сильно наворочено. Зачем надо где-то сохранять указатель на функцию? Что бы потом с ним что? Насколько я понял можно сделать только одну функцию такого типа.

Совершенно верно, можно сделать одну функцию со switch/case, я раньше так и делал. Теперь решил сделать более объектно-ориентированно. Отлично
NetRaider, спасибо за разъяснения.
Записан
NetRaider
Гость
« Ответ #28 : 01-12-2003 11:12 » 

Опс... ошибся я... Жаль

Цитата
Это определение функции с именем Cmd_01(не являющейся членом класса)
и возвращающая указатель на функцию-член класса CClass, которая в свою очередь, возвращает int.
Эквивалентно:
int CClass::* Cmd_01(ULONG cmd, void *args)
{
return 0;
}
Следует читать:

Это определение функции с именем Cmd_01(не являющейся членом класса)
и возвращающая указатель на переменную(поле) класса CClass, имеющую тип int.

Тогда это выражение(если добавить 'int aaa;' в бъявление класса и переписать функцию так:
Код:
int CClass::* Cmd_01(ULONG, void* args) 
{
    return &CClass::aaa;
}

):


m_c.*Cmd_01(1,0) = 33;

эквивалентно

m_c.aaa = 33;
« Последнее редактирование: 23-11-2007 14:47 от Алексей1153++ » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #29 : 01-12-2003 11:29 » 

dorador, я имел ввиду, в чём разница - вызов функции члена класса через указатель или напрямую, ведь всё происходит в одном классе?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines