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


Автор: Mormishka 26.3.2011, 09:16
Как передать указатель на функцию-член одного класса другому?

Код

typedef int(fun)(int);

class B
{
public:
    fun Myfun;
    B(fun Myfun1)
    {
        this->Myfun=Myfun;
    }
};


class A
{
public:
    B* pB;
    A()
    {
        pB= new B(f);
        this->pB=pB;
    }
    int f(int x)
    {
        return x;
    }
};


Пишет
Код

 error C2659: '=' : overloaded function as left operand

Автор: alexvs11 26.3.2011, 10:43
несколько способов
1) стандартный способ использования указателей на функции-члены, ну тут в гугл
http://www.gamedev.ru/code/faq/?id=3599
2) в стл
Код

#include <iostream>
#include <functional>
#include <algorithm>

class A{
public:
   A( int a ) : m_a(a) {}
   int getA(){ return m_a; }
private:
   int m_a; 
};

int main()
{
   A a( 10 );
   std::mem_fun_t<int, A> fun = std::mem_fun( &A::getA );
   std::cout << fun( &a ); 
}

3) в новом стандарте использования std::function (аналогично в бусте)
Код

#include <functional>
#include <iostream>

struct X {
      int foo(int a) {return a;}
};

int main()
{
   std::function<int (X*, int)> f;
   f = &X::foo;      // pointer to member

   X x;
   std::cout << f(&x, 5); // call X::foo() for x with 5
} 


Добавлено через 1 минуту и 18 секунд
главное помнить, что указатель на функцию член зависит от двух вещей
1) смещение в классе, те &X::foo
2) адреса самого объекта

Автор: bsa 26.3.2011, 11:15
Цитата(alexvs11 @  26.3.2011,  10:43 Найти цитируемый пост)
главное помнить, что указатель на функцию член зависит от двух вещей
1) смещение в классе, те &X::foo
2) адреса самого объекта 

Да что ты?!?  smile 
Сколько лет знаю С++, но никогда и не догадывался, что размещение подпрограммы в области кода как-то зависит от адреса объекта и количества членов перед ней в определении класса.

Mormishka, тип указателя должен быть int (A::*pFunc)(int). Вызывать нужно так: int r = (a.*pfunc)(x) или int r = (pa->*pfunc)(x), где a - объект типа A, pa - указатель на объект типа A

Автор: jonie 27.3.2011, 12:39
bsa, однако чувак говорит не про подпрограмму, а про сам указатель. И да, он хитрее устроен, чем обычный указатель на функцию (подробнее: http://www.rsdn.ru/article/cpp/delegates.xml#E4GAE) и http://www.rsdn.ru/article/cpp/fastdelegate.xml)

Автор: alexvs11 27.3.2011, 15:36
Цитата(bsa @  26.3.2011,  11:15 Найти цитируемый пост)
Сколько лет знаю С++, но никогда и не догадывался, что размещение подпрограммы в области кода как-то зависит от адреса объекта и количества членов перед ней в определении класса.

ну да, ну да, ну да, а поля объекта как она получает?
данные объекта функция-член получает через указатель this, который является адресом объекта smile  

Автор: mes 27.3.2011, 16:32
Цитата(alexvs11 @  26.3.2011,  09:43 Найти цитируемый пост)
смещение в классе, те &X::foo

Код

struct A
{
  int i;
  void f();
};

Код

struct A
{
  void f();
  int i;
};

_обладает_ ли f() в этих примерах разным смещением ?

Добавлено через 2 минуты и 18 секунд
Цитата(alexvs11 @  27.3.2011,  14:36 Найти цитируемый пост)
анные объекта функция-член получает через указатель this

Цитата(alexvs11 @  26.3.2011,  09:43 Найти цитируемый пост)
что указатель на функцию член
1) смещение в классе, те &X::foo
2) адреса самого объекта 

а указатель на функцию член тоже получает данные через this ?
а то из высказываний не совсем понятно, что имеете ввиду...



Автор: alexvs11 27.3.2011, 16:51
Цитата(mes @  27.3.2011,  16:32 Найти цитируемый пост)
_обладает_ ли f() в этих примерах разным смещением ?

не знаю как их можно сравнить, ибо приведение к int не работает и сравнение для разных классов тоже, но

Код

#include <iostream>

struct A
{
  int i;
  int f(){return i;}
  int g(){return 2*i;} 
};

struct B
{
  void f(){}
   int i; 
};

int main()
{
  std::cout << std::boolalpha << ( &A::f == &A::g );
}  

дает false
Цитата(mes @  27.3.2011,  16:32 Найти цитируемый пост)
а указатель на функцию член тоже получает данные через this ?а то из высказываний не совсем понятно, что имеете ввиду...

скажем так, для доступа к функции-члену нужно смещение и адрес объекта, что в этом не есть очевидное?
ну уж то что виртуальная функция зависит от адреса объекта то уж точно сомнений нет?

Добавлено через 12 минут и 5 секунд
вот собсно ответ на вопрос автора

Код

#include <iostream>

class A;
typedef int (A::*pToFunc)(int);

class B
{
public:   
    B(A* a, pToFunc Myfun1)
    {
        m_fun = Myfun1;
        m_pA = a;
         
        std::cout << ( m_pA->*m_fun )( 10 );
    }
private:
    A* m_pA;
    pToFunc m_fun;  
};


class A
{
public:
    B* pB;
    A()
    {
        pB = new B(this, &A::f);
        this->pB=pB;
    }
    int f(int x)
    {
        return x;
    }
    int g(int x)
    {
        return 2*x;
    } 
};

int main()
{
  A a;
}

Автор: mes 27.3.2011, 17:19
Цитата(alexvs11 @  27.3.2011,  15:51 Найти цитируемый пост)
скажем так, для доступа к функции-члену нужно смещение и адрес объекта, что в этом не есть очевидное?

1. смещение функции в чем ?
2. для доступа к функции-члену адрес объекта не нужен.. 
а для вызова функции члены только адреса объекта мало, нужен и тип.. 
3. указатель на функцию и имя функции имеют разное поведение ( при вызове)


Автор: alexvs11 27.3.2011, 17:22
Цитата(mes @  27.3.2011,  17:19 Найти цитируемый пост)
для доступа к функции-члену адрес объекта не нужен.. а для вызова функции члены только адреса объекта мало, нужен и тип.. 

ну дак ответьте автору без адреса объекта

Автор: mes 27.3.2011, 17:24
Цитата(alexvs11 @  27.3.2011,  15:51 Найти цитируемый пост)
ну уж то что виртуальная функция зависит от адреса объекта то уж точно сомнений нет

от самого адреса объекта нет smile 
smile

Автор: alexvs11 27.3.2011, 17:26
это умная демагогия про то чем отличается функция от ее вызова?

Автор: mes 27.3.2011, 17:27
Цитата(alexvs11 @  27.3.2011,  16:22 Найти цитируемый пост)
ну дак ответьте автору без адреса объекта 

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

Автор: bsa 27.3.2011, 19:18
Цитата(jonie @ 27.3.2011,  12:39)
bsa, однако чувак говорит не про подпрограмму, а про сам указатель. И да, он хитрее устроен, чем обычный указатель на функцию (подробнее: http://www.rsdn.ru/article/cpp/delegates.xml#E4GAE) и http://www.rsdn.ru/article/cpp/fastdelegate.xml)

Почитал. Узнал много нового. Спасибо.
Знал, что указатель на метод вещь убогая, но даже не представлял, что на столько.

Автор: alexvs11 27.3.2011, 19:40
Цитата(bsa @  27.3.2011,  19:18 Найти цитируемый пост)
Знал, что указатель на метод вещь убогая, но даже не представлял, что на столько

поэтому радуемся std::function

Автор: mes 27.3.2011, 19:57
Цитата(alexvs11 @  27.3.2011,  18:40 Найти цитируемый пост)
поэтому радуемся std::function 

это не пройдет когда нам нужно сделать из метода  с-делегат ( например void(*cb)(void *); )

Автор: alexvs11 27.3.2011, 20:19
Цитата(mes @  27.3.2011,  19:57 Найти цитируемый пост)
это не пройдет когда нам нужно сделать из метода  с-делегат ( например void(*cb)(void *); )

Код

#include <functional>
#include <iostream>

class A
{
public:
  void OnMessage(void* message)
  {
      std::cout << reinterpret_cast<char*>( message ) << std::endl;
  }  
};

void SendMsg( std::function<void (void*)>& f ) 
{
   f( (void*)"hello world" );
}

int main()
{
   A a;
   std::function<void (void*)> f = 
        std::bind1st(std::mem_fun(&A::OnMessage), &a);
   SendMsg( f ); 
}

нечто вроде этого, или чтото другое?

Автор: mes 27.3.2011, 20:34
Цитата(alexvs11 @  27.3.2011,  19:19 Найти цитируемый пост)
нечто вроде этого, или чтото другое? 

типо этого
Код

#include <iostream>

typedef void (action)(void *);

void test (action * act, void * arg)
{
    std::cout << "begin ";
    act(arg);
    std::cout << "end " << std::endl;
}

struct A
{
   std::string str;
};

void fn (A * a)
{
   if (a) std::cout << a->str;
}

int main ()
{
   A a = { "do " };
   test ((action*)fn, &a);    
}

1. передавать test`у std::function не получится
2. прямая конверсия метода (где fn нестатический член А) не безопасна
какой вариант можете предложить ?

т.е. для условно такого :
Код

struct A
{
   std::string str;
   void fn (){..};
};


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