как определить хитрый указатель...
От: PaNov Россия  
Дата: 05.03.02 17:25
Оценка:
есть:
typedef double (*FuncGetParam)(int i,int j);
// некий класс, содержащий указатель на функцию
class A
{
public :
FuncGetParam func; // указатель на функцию
double getParam(int i, int j);
};

// это произвольный класс
class B
{
public :
double getParam(int i, int j);
};

// это произвольная функция...
double freeGetParam(int i, int j)
{
return 1.0;
}

надо сделать так, чтобы чтобы можно было присвоить указатель на произвольную функцию (совпадающую по передаваемым параметрам и возвращаемому результату), которая может быть как в самом классе "A", в другом классе "B", а может быть и просто отдельной функцией!

{
A a;
B b;
// надо, чтобы все эти варианты могли работать
A.func = a.getParam;
A.func = b.getParam;
A.func = freeGetParam;
}

в С++ Builder это делается определением функции вот таким способом:
typedef double (__closure *FuncGetParam)(int i,int j);
ключевое слово — "__closure"
как такое же сделать в Visual C++ ?????
если стандартными способами это не делается, покажите, как реализовать нестандартными...
большой сенк!
Re: как определить хитрый указатель...
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 05.03.02 18:19
Оценка:
Здравствуйте PaNov, Вы писали:

PN>есть:

PN>typedef double (*FuncGetParam)(int i,int j);
PN>// некий класс, содержащий указатель на функцию
PN>class A
PN>{
PN> public :
PN> FuncGetParam func; // указатель на функцию
PN> double getParam(int i, int j);
PN>};

PN>// это произвольный класс

PN>class B
PN>{
PN> public :
PN> double getParam(int i, int j);
PN>};

PN>// это произвольная функция...

PN>double freeGetParam(int i, int j)
PN>{
PN> return 1.0;
PN>}

PN>надо сделать так, чтобы чтобы можно было присвоить указатель на произвольную функцию (совпадающую по передаваемым параметрам и возвращаемому результату), которая может быть как в самом классе "A", в другом классе "B", а может быть и просто отдельной функцией!


PN>{

PN> A a;
PN> B b;
PN> // надо, чтобы все эти варианты могли работать
PN> A.func = a.getParam;
PN> A.func = b.getParam;
PN> A.func = freeGetParam;
PN>}

PN>в С++ Builder это делается определением функции вот таким способом:

PN>typedef double (__closure *FuncGetParam)(int i,int j);
PN>ключевое слово — "__closure"
PN>как такое же сделать в Visual C++ ?????
PN>если стандартными способами это не делается, покажите, как реализовать нестандартными...

Стандартными способами это не делается.

1. Все в порядке для обычных функций и для статических методов классов. Эта техника сработает.
2. Все плохо для нестатических методов классов. В общем случае (описано в Стандарте) вызов нестатического метода через указатель должен осуществляться принепосредственном участии объекта, для которого делается вызов. Обычным приведением типов это делается для случая одиночного наследования (см. http://rsdn.ru/forum/message.asp?mid=24451
Автор: Андрей Тарасевич
Дата: 26.01.02
и вокруг. Ссылку проверить не могу, т.к. сервер еле шевелится.) Как же написано в том сообщении, которое я имею ввиду, ситуация с таким приведением для случая множественного наследования "... не будет работать в ста процентов случаев." (с) Андрей Тарасевич (когда сервак оживет, можно поиск по этой фразе устроить). В этом случае информация о смещении текущей таблицы вирт. функций (в которой находится вызываемый тобой метод) тепряется, и могут быть варианты.

С уважением
Алексей Кирдин
Re: как определить хитрый указатель...
От: Gambler  
Дата: 06.03.02 07:23
Оценка:
Здравствуйте PaNov, Вы писали:

PN>есть:

PN>typedef double (*FuncGetParam)(int i,int j);

PN> // надо, чтобы все эти варианты могли работать

PN> A.func = a.getParam;
PN> A.func = b.getParam;
PN> A.func = freeGetParam;


Всё дело в том, что a.getParam и b.getParam на самом деле имеют вид
getParam(A *this,int i, int j) для класса A и для B соответственно потому как они не статические, так что как видишь несоответствие типов тут, поэтому и не работает.
-------------------------------------------------------------------

Вызывает презедент к себе коров и говорит:
— Ну, что будем сдавать, молоко или мясо?
(с) Г. Явлинский TV6 — Герой дня (18.04.2002)
Re: как определить хитрый указатель...
От: Аноним  
Дата: 06.03.02 11:41
Оценка:
Здравствуйте PaNov, Вы писали:

PN>есть:

PN>typedef double (*FuncGetParam)(int i,int j);
PN>// некий класс, содержащий указатель на функцию
PN>class A
PN>{
PN> public :
PN> FuncGetParam func; // указатель на функцию
PN> double getParam(int i, int j);
PN>};

PN>// это произвольный класс

PN>class B
PN>{
PN> public :
PN> double getParam(int i, int j);
PN>};

PN>// это произвольная функция...

PN>double freeGetParam(int i, int j)
PN>{
PN> return 1.0;
PN>}

PN>надо сделать так, чтобы чтобы можно было присвоить указатель на произвольную функцию (совпадающую по передаваемым параметрам и возвращаемому результату), которая может быть как в самом классе "A", в другом классе "B", а может быть и просто отдельной функцией!


PN>{

PN> A a;
PN> B b;
PN> // надо, чтобы все эти варианты могли работать
PN> A.func = a.getParam;
PN> A.func = b.getParam;
PN> A.func = freeGetParam;
PN>}

Первые два варианта работать не будут, да и не должны. Иначе получилось бы что ты можешь вызвать метод класса неотносящийся к конкретному объекту, экземляру этого класса — а это нонсенс. Помоему тут проблема с дизайном программы и взаимосвязи классов.

Best regards,
sky
Re: как определить хитрый указатель...
От: Botan2  
Дата: 06.03.02 12:45
Оценка:
Здравствуйте PaNov, Вы писали:

PN>в С++ Builder это делается определением функции вот таким способом:

PN>typedef double (__closure *FuncGetParam)(int i,int j);
PN>ключевое слово — "__closure"
PN>как такое же сделать в Visual C++ ?????
PN>если стандартными способами это не делается, покажите, как реализовать нестандартными...
PN>большой сенк!

Я реализовал средствами Visual C++ нечто подобное пиши мне на мыло. В Форуме места не хватит
Re[2]: как определить хитрый указатель...
От: Павел Кузнецов  
Дата: 06.03.02 12:52
Оценка:
Kaa>2. Все плохо для нестатических методов классов. В общем случае (описано в Стандарте) вызов нестатического метода через указатель должен осуществляться принепосредственном участии объекта, для которого делается вызов. Обычным приведением типов это делается для случая одиночного наследования (см. http://rsdn.ru/forum/message.asp?mid=24451
Автор: Андрей Тарасевич
Дата: 26.01.02
и вокруг. Ссылку проверить не могу, т.к. сервер еле шевелится.) Как же написано в том сообщении, которое я имею ввиду, ситуация с таким приведением для случая множественного наследования "... не будет работать в ста процентов случаев." (с) Андрей Тарасевич (когда сервак оживет, можно поиск по этой фразе устроить). В этом случае информация о смещении текущей таблицы вирт. функций (в которой находится вызываемый тобой метод) теряется, и могут быть варианты.


Насколько я понимаю, это дело поправляется комбинацией описанного подхода с генерацией промежуточных функций для вызова методов. Вот пример генератора для вызова метода с двумя аргументами:

template<class R, class T, class A1, class A2, R(T::*m)(A1, A2)>
R method_thunk(T* t, A1 a1, A2 a2)
{
  return (t->*m)(a1, a2);
}


В результате можно слегка поправить предложенный парнями из Microsoft класс и передавать в него вместо &A::getParam адрес соответствующей промежуточной функции: method_thunk<double, A, int, int, &A::getParam>. Такой подход будет работать и в случае множественного или виртуального наследования.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: как определить хитрый указатель...
От: Gambler  
Дата: 07.03.02 09:35
Оценка:
Здравствуйте Botan2, Вы писали:

B>Я реализовал средствами Visual C++ нечто подобное пиши мне на мыло. В Форуме места не хватит


Бритвы Окамма на вас нет!
-------------------------------------------------------------------

Вызывает презедент к себе коров и говорит:
— Ну, что будем сдавать, молоко или мясо?
(с) Г. Явлинский TV6 — Герой дня (18.04.2002)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.