| 
			| 
					
						| 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 от Мейерса, там очень хорошо описана работа этого адаптера |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |