Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Указатели на функции-члены


Автор: BabySG 30.9.2005, 20:00
Есть следующее построение:
Код

class Base{
   // Что-то там...
};

class A : public Base {
   void fA();
};

class B : public Base {
   void fB();
};

class D{
   void fD( /* вот тут-то и вопрос */ );
};


Как передать в fD() указатели на fA() и fB()?

Если написать в виде Base::* - не катит smile... Прочитал кучу литературы, понял, почему не катит, но вот как сделать - не понял... Кто поможет?

Автор: Mad 30.9.2005, 20:08
Код

class Base{
   virtual void fA();
   virtual void fB();
};

class A : public Base {
   virtual void fA();
};

class B : public Base {
   virtual void fB();
};

class D{
   void fD(Base* classA, Base* classB)
   {
        classA->fA();
        classB->fB();
    }
};


Автор: BabySG 30.9.2005, 20:11
Собственно, только что читал про это недалеко на форуме smile

Так вот - не катит smile

Классы А и Б - тут упрощенно приведено - их порядка 100... Количество функции - соотвественно..
Не прописывать же каждую в базовый!
(Вдобавок - могут иметь одинаковые названия - но разные реализации )

Далее: вопрос может встать так, что и базовый может быть другой.
Т.е. нужен вариант void*, только для функций-членов...

Автор: Mad 30.9.2005, 20:18
Цитата(BabySG @ 30.9.2005, 19:11)
Т.е. нужен вариант void*, только для функций-членов...

без указателя на обьект класса не обойдешся.

правда есть два варианта
1. сделать эти функции static (тогда на них можно взять void* указатель)
fD((void*)class->function);

2. тут уже нужен указатель на класс и немного asm, просто лубой вызов
class->function();
реально преобразуеться в
function(class*);
Добавлено @ 20:20
А вообщето опиши задаче по потробней (откуда необходимость передавать именно указатель на ф-цию член класса), может просто есть решение общей проблеммы и без указателей на функции ?

Автор: BabySG 30.9.2005, 20:22
1) Статик не пройдет, к сожалению (уже подумывал...)
2) Не понял...?

Вопрос: как такое реализованно в MFC и их классе CCmdTarget
А то я начал ковырять их message map и завяз по самое не балуй...

Смысл только уловил, что каждый объект, который реагирует, должен быть наследован от CCmdTarget и как-то все указатели приводятся к его типу.

Соответственно: как у них это работает? smile


Цитата
А вообщето опиши задаче по потробней (откуда необходимость передавать именно указатель на ф-цию член класса), может просто есть решение общей проблеммы и без указателей на функции ?


Упрощенно:

Есть объект, у которого есть окна. В окне нажали на кнопку и вызвалась определенная функция из массива событий. Причем окно даже не знает что/где/зачем. Соотвественно - при создания окна нужно зарегистрировать функцию на событие в этом окне.

PS. Вариант, а-ля TurboVision не проходит - системы обработки эвентов нет и не будет.

Автор: Mad 30.9.2005, 20:43
Цитата(BabySG @ 30.9.2005, 19:22)
Есть объект, у которого есть окна. В окне нажали на кнопку и вызвалась определенная функция из массива событий. Причем окно даже не знает что/где/зачем.


Цитата(BabySG @ 30.9.2005, 19:22)
Вопрос: как такое реализованно в MFC и их классе CCmdTarget
А то я начал ковырять их message map и завяз по самое не балуй...


Тебе под что надо, под MFC или под WinAPI ?

Автор: BabySG 30.9.2005, 21:50
MFC мне даром не нужен smile

У меня свои "окна"...

Автор: Mad 30.9.2005, 21:59
Цитата(BabySG @ 30.9.2005, 20:50)
У меня свои "окна"...

что значит это "свои окна"
решение задачи, которую ты описал, сильно зависит от архитектуры всего Framework в котором она бедет реализованна.

какие либы ты используеш, или чистый WinAPI ?

Автор: BabySG 30.9.2005, 23:29
Mad
Огромное спасибо за желание помочь!

Случайно наткнулся на книженцию Андрея Александреску и там есть решение этой задачи.

Автор: Mad 30.9.2005, 23:56
Цитата(BabySG @ 30.9.2005, 22:29)
Случайно наткнулся на книженцию Андрея Александреску и там есть решение этой задачи.

Ну так выкладывай общий принцып суда, может еще кому поможет
(или может нет, тут много постов типа прочитал в книге, а реально не работает smile)

Автор: Earnest 1.10.2005, 08:59
Цитата(BabySG @ 30.9.2005, 20:22)
Вопрос: как такое реализованно в MFC и их классе CCmdTarget
А то я начал ковырять их message map и завяз по самое не балуй...


MFC просто грубо приводит функции-обработчики к нужной сигнатуре. В реализации MS размер указателя на функцию- член равен 4 байтам, также как на "обычную".
Соответственно, MFC очень сильно полагается на то, что обработчик будет строго соответствовать требуемой сигнатуре. Если где-то ошибится - потом с отладкой умучаешься. Особенно когда в дебаге работает, а в релизе валится, что запросто.
Но это уже smile
А для твоей задачи идеально подходит boost::function + boost::bind.
Выглядит примерно так. Сначала обявляешь обработчик с нужной сигнатурой:
Код

typedef boost::function<void(int,double)> CHandler;

т.е. требуется (будет вызываться) функция принимающая 2 параметра (int,double) и возвращающая void.
Потом в объект CHandler можно запихнуть все, что угодно - функтор, свободную функцию, функцию-член, хоть виртуальную, хоть нет - без разницы. Даже число ее параметров не должно строго соответствовать (просто нужно правильно написать bind).
Допустим, есть такой класс:
Код

class A
{
   void BBB(double);
};

Присваиваем:
Код

A a;
CHandler _handler = boost::bind(A::BBB,&a,_2);
Это значит, что будет передан второй аргумент вызова (double), а первый (int) проигнорирован.
Вызов - элементарный:
Код

int p1;
double p2;
if (_handler) _handler(p1,p2);


Автор: BabySG 1.10.2005, 12:54
Earnest
Благодарствую - будем разбираться с boost, а так не хотелось smile

Mad
Хм, там целая глава и, собственно, приходят почти к варианту boost:function

Сейчас буду пробовать и так и так...
Добавлено @ 12:57
Интересно, а если в классе прописать такой вариант:
Код

template <class TOwner> void fD(TOwner* pOwner,void(TOwner::* func)(void)){
    (pOwner->*func)();
}


Что будет в плане производительности?
Да и как потом созранить эти указатели в одном массиве....?

Автор: Earnest 1.10.2005, 20:41
http://www.rsdn.ru/article/cpp/fastdelegate.xml и реализацию делегатов...

Автор: BabySG 1.10.2005, 21:38
Цитата(Earnest @ 1.10.2005, 20:41)
http://www.rsdn.ru/article/cpp/fastdelegate.xml и реализацию делегатов...

Спасибо - читал и не раз.
Статья действительно шикарная, но хотелось бы большего...

Хм... Покумекав немного, пришел к мысли, что мне проще передать структуру в fD(), которая содержит в себе указатель на объект и указатель на функцию-член.
Т.е.:
Код

template < TObj >
struct MyStruct{
   TObj *obj;
   void (TObj::*method)( void );
};

void D::fD( MyStruct * st ){
   // что-то там...
};


Тем самым мне совершенно плевать, на что там и где указывает + могу сохранить все это дело в массиве/списке и потом порыться там...

Мнения?

Добавлено: тормоз - только написал и понял, что работать не будет smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)