sss
Специалист
Offline
|
|
« : 04-07-2003 04:27 » |
|
Подскажите кто может (пытаюсь перелезть на VC из Delphi), как получить указатель на виртуальный метод класса в VC ? В Delphi аналог есть, директива of object. Явно заданный this выходом не считаю. Заранее спасибо.
|
|
|
Записан
|
while (8==8)
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #1 : 04-07-2003 06:39 » |
|
Давай разберемся. Мне не очень понятно - в свете того что Дельфи я не знаю, почему тебе не подходит this и почему указатель на виртуальную функцию...
Ведь виртуальная ф-ия без тела по сути может не иметь тела и должна быть переопределена в классе наследнике. А ты требуешь указатель на что??
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #2 : 04-07-2003 06:55 » |
|
Ведь виртуальная ф-ия без тела по сути может не иметь тела и должна быть переопределена в классе наследнике.
Чтой-то Вы, ваше величество, замысловато завернули. Из этой фразы вытекает, что виртуальная ф-ия без тела по сути (или без сути) может тело все-таки иметь
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #3 : 04-07-2003 07:06 » |
|
Предположим у нас такой код #include "stdafx.h" #include <iostream.h>
class Base { public: Base(){;}; virtual ~Base(){;}; virtual void A()=0; };
class Derived: public Base { int x; public: virtual ~Derived(){;}; Derived():Base(),x(10){;}; virtual void A(){ cout<<this->x<<endl; }; };
int _tmain(int argc, _TCHAR* argv[]) { Derived d,*ptrd; d.A(); return 0; }
как получить адрес d.A()? Так вопрос что ли стоит. Адрес ее конечно есть, и хранится в таблице вызовов экземпляра класса, но вот как его получить не привязываясь к конкретной платформе и компилятору, то есть на чистом C++ я пока не знаю. И по моему стандарт языка такой возможности не предусматривает, так как имея адрес вызвать ее не удастся, надо еще ей передать указатель this, а это платформенно и компиляторно зависимая вещь.
|
|
« Последнее редактирование: 18-11-2007 06:16 от Алексей1153++ »
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #4 : 04-07-2003 07:29 » |
|
Ведь виртуальная ф-ия без тела по сути может не иметь тела и должна быть переопределена в классе наследнике.
Чтой-то Вы, ваше величество, замысловато завернули. Из этой фразы вытекает, что виртуальная ф-ия без тела по сути (или без сути) может тело все-таки иметь Да, имелось в виду, что непонятно на каком этапе нужен указатель - возможно человек просто не понял сути виртуальных функций и хочет указатель на саму виртуальную функцию без переопределения. Слава - так то что ты сказал - для любой функции класса, не только виртуальной. И ИМХО речь вроде идет о VC поэтому я и попросил уточнить
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Lex
|
|
« Ответ #5 : 04-07-2003 07:31 » |
|
Адрес ее конечно есть, и хранится в таблице вызовов экземпляра класса, но вот как его получить не привязываясь к конкретной платформе и компилятору, то есть на чистом C++ я пока не знаю. И по моему стандарт языка такой возможности не предусматривает, так как имея адрес вызвать ее не удастся, надо еще ей передать указатель this, а это платформенно и компиляторно зависимая вещь
Истино так. может зависеть даже от версии компилятора.
|
|
|
Записан
|
Megabyte be with you!
|
|
|
sss
Специалист
Offline
|
|
« Ответ #6 : 04-07-2003 07:43 » |
|
Давай разберемся. Мне не очень понятно - в свете того что Дельфи я не знаю, почему тебе не подходит this и почему указатель на виртуальную функцию...
Ведь виртуальная ф-ия без тела по сути может не иметь тела и должна быть переопределена в классе наследнике. А ты требуешь указатель на что?? ну я в смысле не абстрактная, .... блин, как трудно объяснить, к Дельфи привык. Там надстройка к системе сообщений так построена. Есть переменная в родителе указывающая на функцию в его потомках(и не только). Родитель смотрит, указатель не пустой, и вызывает метод. Это позволяет разгрузить WndProc. Директива of object используется при описании типа. type TNotifyEvent: procedure(Sender: TObject); of object; TBase = class procedure NotifyEvent(Sender: TObject); virtual; // тело должно быть // в Delphi вот так procedure NotifyEvent(Sender: TObject); abstract; // тела нет TClassA = class A: TNotifyEvent; end; TClassB = class(TBase) procedure NotifyEvent(Sender: TObject); override; end; TClassC = class(TBase) procedure NotifyEvent(Sender: TObject); override; end; var P: TNotifyEvent; // B: TClassB; C: TClassC; begin ... P := B.NotifyEvent; // метод B и self на месте P(nil); P := C.NotifyEvent; // метод С и self на месте P(nil); ... end; А в VC получается только со статикой. Думал, есть стандартная заковырка в VС про которую не знаю. Это все можно решить, если описать структуру с this и jmpptr, плюс при вызове данной функции asm включить. Так вроде asm нельзя использовать в макросах С, т.е. будет больно. P.S: Я пока примеры на С не буду показывать, а то опозорюсь совсем жду ответ on-line. На выходных надо учиться, а доступа к Вам нет !
|
|
|
Записан
|
while (8==8)
|
|
|
Lex
|
|
« Ответ #7 : 04-07-2003 07:52 » |
|
А для чего тебе это надо? IMHO, если в цикле вызвать виртуальный метод для какого-нить массива/списка объектов, то указатель на виртуальную функцию и не нужен.
|
|
|
Записан
|
Megabyte be with you!
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #8 : 04-07-2003 07:59 » |
|
Это все можно решить, если описать структуру с this и jmpptr, плюс при вызове данной функции asm включить. Так вроде asm нельзя использовать в макросах С, т.е. будет больно.
P.S: Я пока примеры на С не буду показывать, а то опозорюсь совсем жду ответ on-line. На выходных надо учиться, а доступа к Вам нет ! Насчет __asm никаких ограничений нет, так как макрос просто подставляется в код препроцессором. Есть только ограничение в 64 разрядных компиляторах- они __asm больше не делают, убран встроенный ассемблер.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #9 : 04-07-2003 08:02 » |
|
Я думаю(как и Слава) что ты его иначе как из таблицы вертуальных функций не получишь. Потому как метод класса при комниляции заменяется не адресом а индексом. И у метода класса есть скрытый параметр this
Объясни пожалуста что ты хочешь сделать?
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
sss
Специалист
Offline
|
|
« Ответ #10 : 04-07-2003 08:56 » |
|
Я думаю(как и Слава) что ты его иначе как из таблицы вертуальных функций не получишь. Потому как метод класса при комниляции заменяется не адресом а индексом. И у метода класса есть скрытый параметр this
Объясни пожалуста что ты хочешь сделать? 1. Менять вызов функции динамически 2. Создавать подписи на вызов в виде очереди 3. Динамически подключать/отключать класс к классу Вообще то идей куча, реализации есть... на дельфи , Данных по VMT (как строится) нет.
|
|
|
Записан
|
while (8==8)
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #11 : 04-07-2003 09:18 » |
|
Что- то я не совсем понимаю, что собственно надо... :?: 1. Менять вызов функции динамически
Что сие означает - вызов функции по сообщению или прямой вызов- и что мешает работать в case 2. Создавать подписи на вызов в виде очереди
Это у меня вобще ассоциации вызвало только с очередями за колбасой - какие подписи??? 3. Динамически подключать/отключать класс к классу
Так это - в смысле - объявляй поинтер и конструируй класс и дестрой его сколько влезет
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #12 : 04-07-2003 09:26 » |
|
Может я опять что-то не понимаю , но похоже это те же грабли, которые обсуждались в топике про BCB. Если я правильно понял заключительные выступления в том топике, то в ВСВ (читай в Дельфи) виртуальность для обработки сообщений реализована следующим образом: в классе-папе описаны переменные типа указатель на функцию обработки сообщений, а все классы-детки присваивают этим переменным указатели на собственные методы. Ну а при обработке сообщений берется значение переменной. Такое на VC повторить можно, но все-таки сложно. Есть гораздо более элегантные решения. Или я опять не правильно понял?
|
|
|
Записан
|
|
|
|
Lex
|
|
« Ответ #13 : 04-07-2003 09:27 » |
|
Цитата: 1. Менять вызов функции динамически Что сие означает - вызов функции по сообщению или прямой вызов- и что мешает работать в case По-моемому решение этогонедавно обсуждалось в теме по событиям в BCB. Указатель на функцию и присваивай ему чего тебе надо. Цитата:
2. Создавать подписи на вызов в виде очереди
Это у меня вобще ассоциации вызвало только с очередями за колбасой - какие подписи???
На сколько я понял это примерно так, только очередь за вожможностью исполнить функцию.
|
|
|
Записан
|
Megabyte be with you!
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #14 : 04-07-2003 09:28 » |
|
1. Менять вызов функции динамически
меняешь указатель на класс и вызвашь разные ф-ции, если они не виртуальные. 2. Создавать подписи на вызов в виде очереди
Тоже не понял Динамически подключать/отключать класс к классу
Храни указатели и подключай сколько хочешь, delete не забывай вызывать.
|
|
« Последнее редактирование: 15-04-2006 06:27 от Алексей1153 »
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #15 : 04-07-2003 09:33 » |
|
Во во - похоже Лекс и Дилетант правы - была уже темка ... Второе - мне кажется легче все ж таки работать не с указателями, а с выбором функции через switch - case так мы не заставляем систему изгибаться.
Суть в том, что VC реагирует на любое сообщение стандартной функцией - которая зачастую обязательна для вызова, иначе нихрена не работает.
При этом можно осуществлять перехват на свою функцию, а потом в ней вызывать прямо из класса CDialog::OnChar() к примеру...
Если надо сделать разные обработчики - берется условие и дели - какие из простых ф-ий ты будешь когда вызывать и решай дергать ли собственный вынь обработчик или нет...
Насчет очереди - все надо делать ручками ...
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #16 : 04-07-2003 09:38 » |
|
Сравни коды этих двух программ, и реши что тебе нужно #include <iostream.h>
class Base { public: Base(){;}; virtual ~Base(){;}; virtual void A(){ cout<<"Class Base\n"<<endl;}; };
class Derived: public Base { int x; public: virtual ~Derived(){;}; Derived():Base(),x(10){;}; virtual void A(){ cout<<"Class Derived\n"<<endl;}; };
int _tmain(int argc, _TCHAR* argv[]) { Derived d; Derived* ptrd = &d; Base* ptrb = &d; ptrb->A(); ptrd->A(); return 0; }
#include <iostream.h>
class Base { public: Base(){;}; virtual ~Base(){;}; void A(){ cout<<"Class Base\n"<<endl;}; };
class Derived: public Base { int x; public: virtual ~Derived(){;}; Derived():Base(),x(10){;}; void A(){ cout<<"Class Derived\n"<<endl;}; };
int _tmain(int argc, _TCHAR* argv[]) { Derived d; Derived* ptrd = &d; Base* ptrb = &d; ptrb->A(); ptrd->A(); return 0; }
|
|
« Последнее редактирование: 18-11-2007 06:26 от Алексей1153++ »
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #17 : 04-07-2003 10:50 » |
|
То что ты описал (1,2,3) это очень похоже на СОМ это их идеи, позднее связываение, динамическая замена компонента.
За то что это именно так говорит еще и то что идея наследована из билдера и делфи они орентированы на эту технологию и включают в себя библиотеки построеные на ней.
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #18 : 04-07-2003 13:55 » |
|
А вот так можно попробовать указатель получить. Проблема получения указателя в том, что у него дурацкий тип вызова. У Майкросфт это _thiscall. Поэтому надо извращаться. Например так-
#include "stdafx.h" #include <iostream.h>
class FuncPointer { };
typedef (FuncPointer::*FPOINT)();
class Base { public: Base(){;}; virtual ~Base(){;}; virtual void A(){ cout<<"Class Base\n"<<endl;}; };
class Derived: public Base { int x; public: virtual ~Derived(){;}; Derived():Base(),x(10){;}; virtual void A(){ cout<<"Class Derived\n"<<endl; }; FPOINT GetAddressOfA(){ return FPOINT(A);}; };
int _tmain(int argc, _TCHAR* argv[]) { Derived d; Derived* ptrd = &d; Base* ptrb = &d; ptrb->A(); ptrd->A(); FPOINT pf = ptrd->GetAddressOfA();// что с этим дальше делать? return 0; }
|
|
|
Записан
|
|
|
|
chaka
Гость
|
|
« Ответ #19 : 05-07-2003 13:01 » |
|
А может все проще, может нужно просто сделать так: #include <iostream> //for cout #include <iomanip> //for endl #include <stdlib.h> //for EXIT_SUCCESS
class Base{ typedef int (Base::*Func)(); //pointer to member function protected: Func func; public: Base(){ this->func = &Base::some_func; } virtual ~Base(){ } int run(){ return (this->*func)(); } virtual int some_func(){ std::cout << "Base::some_func" << std::endl; return EXIT_SUCCESS; } };
class Derived : public Base{ public: Derived(){ } virtual ~Derived(){ } virtual int some_func(){ std::cout << "Derived::some_func" << std::endl; return EXIT_SUCCESS; } };
int main(int argc, char *argv[]){ Base base_obj; base_obj.run(); //Base::some_func Derived derived_obj; derived_obj.run(); //Derived::some_func return EXIT_SUCCESS; }
|
|
« Последнее редактирование: 18-11-2007 06:29 от Алексей1153++ »
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #20 : 06-07-2003 20:25 » |
|
to chaka- конечно можно и так. Просто я поначалу тормозил из-за типа указателя на ф-цию, мне надо было как-то переносимый между компиляторами вариант функтора сделать, поэтому я и сделал пустой класс- его задача обеспечить правильный тип функтора, для успокоения компилятора, а то он никак не хотел компилить.
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #21 : 07-07-2003 03:16 » |
|
SlavaI !!! Класс, в смысле круто !!! class FuncPointer { }; typedef (FuncPointer::*FPOINT)(); Я продолжу твой код: ... FPOINT pf = ptrd->GetAddressOfA(); __asm { mov eax, ptrd call pf } Зачем мне это надо ?!! Объяснить точнее, что я хочу наверное мне не дано . Скорее всего реакция на нельзя. СПАСИБО !
|
|
|
Записан
|
while (8==8)
|
|
|
sss
Специалист
Offline
|
|
« Ответ #22 : 07-07-2003 04:02 » |
|
Цитата: 1. Менять вызов функции динамически Что сие означает - вызов функции по сообщению или прямой вызов- и что мешает работать в case ответ: case не динамичен По-моемому решение этогонедавно обсуждалось в теме по событиям в BCB. Указатель на функцию и присваивай ему чего тебе надо.
ответ: в том то и дело, что надо было получить этот самый указатель Цитата:
2. Создавать подписи на вызов в виде очереди
Это у меня вобще ассоциации вызвало только с очередями за колбасой - какие подписи???
ответ: давным давно, когда ..., и сегмент ограничивался 64k, и не было динамических массивов и классов контейнеров было такое понятие - очередь.
|
|
|
Записан
|
while (8==8)
|
|
|
sss
Специалист
Offline
|
|
« Ответ #23 : 07-07-2003 04:05 » |
|
То что ты описал (1,2,3) это очень похоже на СОМ это их идеи, позднее связываение, динамическая замена компонента.
За то что это именно так говорит еще и то что идея наследована из билдера и делфи они орентированы на эту технологию и включают в себя библиотеки построеные на ней. Да, именно так. Только плюс RTTI, что-бы поддерживать Invoke. Я тут покопался, RTTI входит как часть стандарта C++.
|
|
|
Записан
|
while (8==8)
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #24 : 14-07-2003 05:34 » |
|
Посмотрел я тут на STL и заметил - к обсуждаемой здесь теме очень близка ф-ция(или класс функтора) mem_fun. Посмотрите ее реализацию в STL- у разных вариантов она разная, находится в заголовочном файле <functional>.
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #25 : 14-07-2003 06:09 » |
|
В дополнение- зачем нужна эта mem_fun. В STL в алгоритмах( например посмотри for_each- он самый простой алгоритм) все ф-ции вызываются как f(x), то есть если алгоритму передать указатель на ф-цию как &Class::Function, такая штука не пройдет, так как превратится в коде в такую вещь Class::Function(p); Ясное дело, что для нестатических членов класса такой вызов незаконен, а необходим такой p->Function(); Вот ф-ция( или класс функтора) mem_fun и делает вызов нормальным по всем правилам.
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #26 : 14-07-2003 10:32 » |
|
А на сайте появилась книга Cтрауструпа- "Язык пррограммирования C++", это наиболее авторитетная книга по C++ от самого надежного автора(он создатель языка), чтется наравне со Стандартом( также лежит на сайте). Книга на сайте на английском, в магазинах ее можно найти на русском. Попробуй там почитать о шаблонах.
|
|
|
Записан
|
|
|
|
Serega
Гость
|
|
« Ответ #27 : 25-07-2003 07:34 » |
|
Если речь идет именно о mem_fun то лучше почитать Effective STL от Мейерса, там очень хорошо описана работа этого адаптера
|
|
|
Записан
|
|
|
|
|