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


Автор: mzconcept 12.5.2008, 07:16
Как реализовать на Visual C++ указатель на функцию-член класса? (в C++ Builder это реализовано с помощью слова __closure)

Автор: Andrey44 12.5.2008, 07:48
Код

void (CSomeDlg::*Funck)() = &CSomeDlg::SomeFunck;

Автор: Lazin 12.5.2008, 08:56
или так:

Код

class A {
    void foo(int param) {}
};

A* inst = new A;

boost::function<void (int)> func = boost::bind(&A::foo, inst, _1);

func(0);//эквивалентно inst->foo(0);

Автор: Earnest 12.5.2008, 16:41
Это не эквивалентные вещи.
Если строго следовать вопросу, то как написал Andrey44:  
 void (CSomeDlg::*Funck)() = &CSomeDlg::SomeFunck; 

Но поскольку автор упомянул closure, то понятно, что ему нужно нечто другое. Это не совсем указатель на функцию-член, а скорее делегат. При вызове функции по чистому указателю нужно будет указывать объект. А чтобы получить готовый вызов - нужно использовать boost, как показал Lazin, ибо в стандартном C++ таких возможностей пока нет.

Автор: Rififi 12.5.2008, 16:42
в tr1 есть
поддерживается в vs2008 with feature pack

Автор: mzconcept 15.5.2008, 07:51
Попробывал так: 
Код

class A {
public:
    typedef void (A::*pf)();
    void fA(){
       MessageBox(NULL, L"fA", NULL, MB_OK);
    }
};
class B : public A {
public:
    pf pff;
    void  fB(){
       MessageBox(NULL, L"fB", NULL, MB_OK);
    }
};
class C : public A{
public:
    void fC() {
       MessageBox(NULL, L"fC", NULL, MB_OK);
    }
};

...

    B b;
    b.pff = &A::fA;
    b.pff = &B::fB; //Error
    b.pff = &C::fC; //Error

    (b.*b.pff3)();


жаль, что не работает...


Потом попробывал второй вариант
Код

typedef void (myfunc)(int a);
class A {
public:
    void foo(int param) {
        
    }
};

...

    A* inst = new A;
    boost::function<myfunc> func = boost::bind(&A::foo, inst, _1);
    func(0);


Работает!!! Одно но, приходиться тянуть библиотеку в 50 метров...

Может попробуем реализовать общими усилиями эту часть буста?

Автор: Earnest 15.5.2008, 08:53
Какую библиотеку? function вся реализована в хедерах. Да, текста там много, но "своими силами" получится не меньше, но хуже... ты бы в исходники заглянул, прежде чем заикаться о другой реализации...

Автор: Lazin 15.5.2008, 09:05
Цитата(mzconcept @  15.5.2008,  07:51 Найти цитируемый пост)
Работает!!! Одно но, приходиться тянуть библиотеку в 50 метров...
Может попробуем реализовать общими усилиями эту часть буста? 

50 метров? кажется ты еще его не собрал  smile 
зы
уже написали что это входит в tr1

Автор: mzconcept 15.5.2008, 13:34
Попытался обойти boost ... вот что получилось:
Код

typedef void (*VMyClick)(void *Owner, int A);

template <class T> class CEvent
{
public:
    void *Owner;
    T Event;
    void Set(void *AOwner, T AEvent)
    {
        Owner = AOwner;
        Event = AEvent;
    }
};


class CApp1
{
public:
...
  static void stClick(void *Owner, int a) 
  {
      ((CApp1*)Owner)->Click(1);
  }
  void Click(int a) 
  {
      int b = a;
  }
};

...

    CEvent<VMyClick> vf;
    vf.Set(App1, stClick);
...
    if (vf.Event != NULL) vf.Event(vf.Owner, 1);


Конечно, недостатком является то, что необходимо описывать дополнительную статическую функцию наподобии static void stClick(...). Зато удобно расспространять исходники своей программы, отпадает необходимость в бусте...

Может кто-нибудь даст совет по оптимизации данного кода?

Автор: Lazin 15.5.2008, 14:22
так и не понял в чем проблема, ты что, рассчитываешь написать программу не использовав ни одной библиотеки что-бы "удобно расспространять исходники своей программы"?
ps
в твоем случае больше подойдет boost::signal, так как там сигналы автоматически отсоединяются от слотов, в случае удаления объекта который их предоставляет.. твой вариант небезопасен, так как ты там систему типов пытаешься обойти (void *Owner;)

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