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
Пол:
|
|
« Ответ #2 : 28-11-2003 09:44 » |
|
А почему не определил как CMD Cmd_01 ? А так похоже несовпадение типов.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
dorador
Гость
|
|
« Ответ #3 : 28-11-2003 10:03 » |
|
Serega, Сделай статической и заработает
статическая функция может работать только со статическими переменными класса - не хотелось бы накладывать такое ограничение RXL, А так похоже несовпадение типов
ругается именно на это А почему не определил как CMD Cmd_01 ?
по-подробнее, пжлста в смысле - как определить-то?
|
|
|
Записан
|
|
|
|
ysv_
Помогающий
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(); } ============================================ Возможны и другие, но ИМХО эти методы небезопасны (базируются на преобразовании типов).
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #5 : 28-11-2003 10:47 » |
|
А почему не определил как 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'
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
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."
|
|
|
|
dorador
Гость
|
|
« Ответ #9 : 28-11-2003 11:23 » |
|
Джон, как RXL посоветовал неработает?
неа как ysv_ посоветовал, работает
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
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
Пол:
|
|
« Ответ #11 : 28-11-2003 11:50 » |
|
А почему не определил как CMD Cmd_01 ?
по-подробнее, пжлста в смысле - как определить-то? Извиняюсь - потропился с ответом - неподумал. Не знаю как на это реагирует VC, а gcc гоаорит следующее: ISO C++ forbids taking the address of a bound member function to form a pointer to member function
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Джон
просто
Администратор
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."
|
|
|
Джон
просто
Администратор
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++ »
|
Записан
|
|
|
|
Джон
просто
Администратор
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
Пол:
|
|
« Ответ #16 : 28-11-2003 13:53 » |
|
Вот-вот - самая интересная часть... Если написать так: CmdEntry Cmd_01(что угодно) {....} , то gcc говорит что я пытаюсь возвращать ф-ию. Если круглые скобки скобки убрать, то: ошибка перед '{'.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Джон
просто
Администратор
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++ »
|
Записан
|
|
|
|
Джон
просто
Администратор
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_
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #23 : 01-12-2003 08:38 » |
|
Это разные вещи - указатель на функцию и указатель на функцию-член класса.
Дык с этим никто и не спорит. Я и не претендую на справедливость моих рассуждений. Обратимся к "первоисточнику"
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.
Просто было интересно поэкспериментировать. Это не является корректным определением функции.
Может быть есть объяснение, почему, скажем так МОЙ , вариант работает? Как работает компилятор в этом случае? По идее я написал то же самое. Только в другом месте.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "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 » |
|
Джон, по твоим рассуждениям написал 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++ »
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #26 : 01-12-2003 10:32 » |
|
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++ »
|
Записан
|
|
|
|
Джон
просто
Администратор
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."
|
|
|
|