есть:
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++ ?????
если стандартными способами это не делается, покажите, как реализовать нестандартными...
большой сенк!
Здравствуйте 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
и вокруг. Ссылку проверить не могу, т.к. сервер еле шевелится.) Как же написано в том сообщении, которое я имею ввиду, ситуация с таким приведением для случая множественного наследования "... не будет работать в ста процентов случаев." (с) Андрей Тарасевич (когда сервак оживет, можно поиск по этой фразе устроить). В этом случае информация о смещении текущей таблицы вирт. функций (в которой находится вызываемый тобой метод) тепряется, и могут быть варианты.
Здравствуйте 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>}
Первые два варианта работать не будут, да и не должны. Иначе получилось бы что ты можешь вызвать метод класса неотносящийся к конкретному объекту, экземляру этого класса — а это нонсенс. Помоему тут проблема с дизайном программы и взаимосвязи классов.
Здравствуйте PaNov, Вы писали:
PN>в С++ Builder это делается определением функции вот таким способом: PN>typedef double (__closure *FuncGetParam)(int i,int j); PN>ключевое слово — "__closure" PN>как такое же сделать в Visual C++ ????? PN>если стандартными способами это не делается, покажите, как реализовать нестандартными... PN>большой сенк!
Я реализовал средствами Visual C++ нечто подобное пиши мне на мыло. В Форуме места не хватит
Kaa>2. Все плохо для нестатических методов классов. В общем случае (описано в Стандарте) вызов нестатического метода через указатель должен осуществляться принепосредственном участии объекта, для которого делается вызов. Обычным приведением типов это делается для случая одиночного наследования (см. http://rsdn.ru/forum/message.asp?mid=24451
и вокруг. Ссылку проверить не могу, т.к. сервер еле шевелится.) Как же написано в том сообщении, которое я имею ввиду, ситуация с таким приведением для случая множественного наследования "... не будет работать в ста процентов случаев." (с) Андрей Тарасевич (когда сервак оживет, можно поиск по этой фразе устроить). В этом случае информация о смещении текущей таблицы вирт. функций (в которой находится вызываемый тобой метод) теряется, и могут быть варианты.
Насколько я понимаю, это дело поправляется комбинацией описанного подхода с генерацией промежуточных функций для вызова методов. Вот пример генератора для вызова метода с двумя аргументами:
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>. Такой подход будет работать и в случае множественного или виртуального наследования.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Botan2, Вы писали:
B>Я реализовал средствами Visual C++ нечто подобное пиши мне на мыло. В Форуме места не хватит
Бритвы Окамма на вас нет!
-------------------------------------------------------------------
Вызывает презедент к себе коров и говорит:
— Ну, что будем сдавать, молоко или мясо?
(с) Г. Явлинский TV6 — Герой дня (18.04.2002)