Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатели на функции-члены, как передать 
:(
    Опции темы
BabySG
Дата 30.9.2005, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



Есть следующее построение:
Код

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

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

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

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


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

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

Это сообщение отредактировал(а) BabySG - 30.9.2005, 20:02
PM MAIL WWW   Вверх
Mad
Дата 30.9.2005, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



Код

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();
    }
};




--------------------
user posted image
PM MAIL   Вверх
BabySG
Дата 30.9.2005, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



Собственно, только что читал про это недалеко на форуме smile

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

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

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

Это сообщение отредактировал(а) BabySG - 30.9.2005, 20:12
PM MAIL WWW   Вверх
Mad
Дата 30.9.2005, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



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

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

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

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


--------------------
user posted image
PM MAIL   Вверх
BabySG
Дата 30.9.2005, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



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

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

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

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


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


Упрощенно:

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

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

Это сообщение отредактировал(а) BabySG - 30.9.2005, 20:28
PM MAIL WWW   Вверх
Mad
Дата 30.9.2005, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



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


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


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


--------------------
user posted image
PM MAIL   Вверх
BabySG
Дата 30.9.2005, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



MFC мне даром не нужен smile

У меня свои "окна"...
PM MAIL WWW   Вверх
Mad
Дата 30.9.2005, 21:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



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

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

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


--------------------
user posted image
PM MAIL   Вверх
BabySG
Дата 30.9.2005, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



Mad
Огромное спасибо за желание помочь!

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

Это сообщение отредактировал(а) BabySG - 30.9.2005, 23:30
PM MAIL WWW   Вверх
Mad
Дата 30.9.2005, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 7
Всего: 19



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

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


--------------------
user posted image
PM MAIL   Вверх
Earnest
Дата 1.10.2005, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(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);




--------------------
...
PM   Вверх
BabySG
Дата 1.10.2005, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



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

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

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

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


Что будет в плане производительности?
Да и как потом созранить эти указатели в одном массиве....?
PM MAIL WWW   Вверх
Earnest
Дата 1.10.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183





--------------------
...
PM   Вверх
BabySG
Дата 1.10.2005, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 26.9.2005

Репутация: нет
Всего: нет



Цитата(Earnest @ 1.10.2005, 20:41)
Шикарная статья про указатели на функции и реализацию делегатов...

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

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

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

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


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

Мнения?

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

Это сообщение отредактировал(а) BabySG - 2.10.2005, 14:29
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0563 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.