2016-04-09 30 views
2

Aynı imzalara sahip olmayan, ancak farklı sınıflardan, eşleşmeyen imzaya sahip bir işlev işaretçisine, statik olmayan üye işlevleri başvurularını nasıl atayabilirim?C++ Eşleşen işlev imzalarıyla herhangi bir sınıfın üye işlevine işaretçi

Bunu, C++ std kitaplığından std::function yardımı ile yapabilirim. Bunu her zaman düzenli C işlevleri ile yapıyorum ve std kütüphanesinden yardım almıyorum. Firmware yazıyor ve kod alanı sınırlı. C++ std kütüphanesinden yardımcılar bunu yapabilirse, kesinlikle C/C++ dil yapılarını kullanarak manuel olarak yapılması mümkün olmalıdır (tercih edilen C++ 11 öncesi). Benim niyet göstermesi

örnek kod:

class A { 
public: 
    void ping_event_handler(); 
}; 

class B { 
public: 
    void ping_event_handler(); 
}; 

void A::ping_event_handler_A() { 
    // Handle ping event in A... 
} 

void B::ping_event_handler_B() { 
    // Handle ping event in B... 
} 

void ping_event_handler_C() { 
    // Handle ping event in normal function... 
} 

int main() { 

    // Ping event "pointer to a function that takes no arguments" 
    void (*ping_event)(); 

    A a(); 
    B b(); 

    ping_event = a.ping_event_handler; // Attach class A's handler 
    ping_event();      // Trigger event 

    ping_event = b.ping_event_handler; // Attach class B's handler 
    ping_event();      // Trigger event 

    ping_event = ping_event_handler; // Attach non-class handler 
    ping_event();      // Trigger event 

} 
+0

Bir başlangıç ​​'A () Yanlıştır. Bu, "a" –

+0

'ping_event = a.ping_event_handler işlevinin bildirilmesidir; - Derleyici bu değere hangi değeri vereceğini nasıl bilir? –

+0

Bu yöntemleri ya statik olarak (nesnenin durumuna gereksinim duymuyorsa) veya sanal (ortak bir temel sınıftan miras alınmış) olarak bildirmeyi düşünün ve işaretçiyi bir temel sınıfa işaret eden bir işleve değiştirin. İşaretçiyi işlevlere ve işaretçiyi yöntemlere karıştırmak isterseniz, std: function olarak bazı sarıcılara ihtiyacınız vardır. – avsmal

cevap

1

eski yolu işlevi

void (*ping_event)(void* userData); 

ile userData geçmek ve fonksiyonu ve userData hem tasarruf etmektir. Daha sonra kullanıcı tarafında , bu sınıfta userData döküm ve ondan bir yöntemin çağrılması:

struct my_function 
{ 
    my_function(void (*f)(void*), void* userData) : mF(f), mUserData(userData) 
    {} 

    void set(void (*f)(void*), void* userData) 
    { 
     mF = f; 
     mUserData = userData; 
    } 

    void operator()() { 
     mF(mUserData); 
    } 
    void (*mF)(void*); 
    void* mUserData; 
}; 

ve çağrı yerinde:

template <typename C, void (C::*m)()> 
void my_func_helper(void* userData) 
{ 
    C* c = static_cast<C*>(userData); 
    (c->*m)(); 
} 


int main() 
{ 
    A a; 

    my_function f(&my_func_helper<A, &A::ping_event_handler>, &a); 

    f(); 

    B b; 

    f.set(&my_func_helper<B, &B::ping_event_handler>, &b); 
    f(); 

    f.set(ping_event_handler_c, NULL); 
    f(); 
} 

Demo

+0

Aferin! Mükemmel çalışır ve std lib veya alt sınıflar içermez. Referans adı için bir işlev çağrısının bir argümanla nasıl görüneceğini ekleyebilir misiniz? Yoksa bu mümkün değil mi? –

+1

İşlev işaretçisi türünü değiştirmeli ve işlev çağrısını değiştirmelisiniz: [Demo] (http://coliru.stacked-crooked.com/a/2458b90c6fad2f52) – Jarod42

İlgili konular