Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Implementacja delegata

Ostatnio zmodyfikowano 2014-03-19 14:35
Autor Wiadomość
maly
Temat założony przez niniejszego użytkownika
[C++] Implementacja delegata
» 2014-03-19 08:11:47
Próbuję zaimplementować prostego delegata i trafiłem na małą przeszkodę, o ile wywołanie bezpośrednio metod klasy
Test
 nie sprawia większych problemów to dostęp do metod klasy
Base
 nie jest możliwy bez jawnego wskazanie zasięgu
Ptr < Test, void( Test::* )( int, float ) > ptr2( Testobject, & Test::Base::f );
 więc mam pytanie co zrobić żeby można było tak
Ptr < Test, void( Test::* )( int, float ) > ptr2( Testobject, & Test::f );
.

C/C++
#include <iostream>

class Base
{
public:
    void f( int a, float b )
    {
        std::cout << "a = " << a << " b = " << b << std::endl;
    }
};

class Test
    : public Base
{
public:
    void f( int a )
    {
        std::cout << "a = " << a << std::endl;
    }
};

template < typename Object, typename Func >
class Ptr
{
    Object mObject;
    Func mFunc;
   
public:
    Ptr( Object o, Func f )
        : mObject( o )
        , mFunc( f )
    {
    }
   
    template < typename A >
    void operator ()( A a )
    {
        ( mObject.* mFunc )( a );
    }
   
    template < typename A, typename B >
    void operator ()( A a, B b )
    {
        ( mObject.* mFunc )( a, b );
    }
};

int main()
{
    Test Testobject;
   
    Ptr < Test, void( Test::* )( int ) > ptr1( Testobject, & Test::f );
    ptr1( 1 );
   
    Ptr < Test, void( Test::* )( int, float ) > ptr2( Testobject, & Test::f );
    ptr2( 2, 3.456f );
   
    return 0;
}
P-106756
DejaVu
» 2014-03-19 09:21:50
Użyj biblioteki FastDelegate zamiast wymyślać koło na nowo. Druga opcja to użyć standardu C++11, ale np. w Visual C++ 2012 nie ma jeszcze wsparcia delegatów na metody.
P-106762
maly
Temat założony przez niniejszego użytkownika
» 2014-03-19 09:40:09
Wiem że istnieją wyspacjalizowane do tego biblioteki jednak ja próbuję to napisać wyłącznie w calach edukacyjno/poznawczych.
Podryfowałem trochę po internecie i wszędzie piszą o vtables np.http://www.codeproject.com​/Articles/7150​/Member-Function-Pointers-and-the-Fastest-Possible które trzeba "ręcznie" przekalkulować, teraz ciekawi mnie to czy rzeczywiście muszę bawić się bezpośrednio ofsetami czy jest to tylko dla owego "fast".
P-106763
DejaVu
» 2014-03-19 12:06:09
C/C++
#include <iostream>

class Base
{
public:
    void f( int a, float b )
    {
        std::cout << "a = " << a << " b = " << b << std::endl;
    }
   
    void g( int a, float b )
    {
        std::cout << "a = " << a << " b = " << b << std::endl;
    }
};

class Test
    : public Base
{
public:
    void f( int a )
    {
        std::cout << "a = " << a << std::endl;
    }
};

template < typename Object, typename Func >
class Ptr
{
    Object mObject;
    Func mFunc;
   
public:
    Ptr( Object o, Func f )
        : mObject( o )
        , mFunc( f )
    {
    }
   
    template < typename A >
    void operator ()( A a )
    {
        ( mObject.* mFunc )( a );
    }
   
    template < typename A, typename B >
    void operator ()( A a, B b )
    {
        ( mObject.* mFunc )( a, b );
    }
};

int main()
{
    Test Testobject;
   
    Ptr < Test, void( Test::* )( int ) > ptr1( Testobject, & Test::f );
    ptr1( 1 );
   
    Ptr < Test, void( Test::* )( int, float ) > ptr2( Testobject, & Base::f ); //TUTAJ ZMIANA
    ptr2( 2, 3.456f );
   
    Ptr < Test, void( Test::* )( int, float ) > ptr3( Testobject, & Test::g ); //TUTAJ ALTERNATYWA
    ptr3( 2, 3.456f );
   
    return 0;
}
Generalnie chodzi o to, że chcesz pobrać adres do metody, która się tak samo nazywa w obu klasach, więc adres klasy bazowej jest przykryty w klasie pochodnej. Powyżej masz rozwiązanie swojego problemu.
P-106767
maly
Temat założony przez niniejszego użytkownika
» 2014-03-19 12:45:42
Ptr < Test, void( Test::* )( int, float ) > ptr2( Testobject, & Base::f );
To jest właśnie sposób którego próbuję się pozbyć.

Ptr < Test, void( Test::* )( int, float ) > ptr3( Testobject, & Test::g );
A to jest tylko ominięcie problemu.

Chodzi mi oto że gdyby metoda klasy
Base::f( int a, float b )
 przeniesiona została do klasy Test działało by to normalnie a teraz mimo że Test dziedziczy po Base to kompilator płacze że niewie co zrobić.

Ten problem wynika chyba bardziej z mojego nierozumienia dziedziczenia bo zawsze wydawało mi się że jeśli dziedziczę to posiadam... :)
P-106770
Monika90
» 2014-03-19 13:52:57
f w klasie Test zasłania f odziedziczone z klasy Base, jeżeli chcesz żeby f było przeciążone, to użyj deklaracji using. Przykład
C/C++
struct B
{
    void f( int );
};

struct D
    : B
{
    using B::f;
    void f( int, int );
};

A poza tym użyj boost.signals
P-106780
maly
Temat założony przez niniejszego użytkownika
» 2014-03-19 14:35:50
@Monika
No ja pierdziu to było takie proste;). Dzięki.
P-106783
« 1 »
  Strona 1 z 1