2012-01-17 85 views
3

是否可以聲明一個函數指針(非C++ 11),它可以指向任何類的成員函數(讀取:不是特定的類)?例如,如果我有類A,B和C. C中有一個函數指針在其中聲明,並且我想在指向B的成員函數之一和A的成員函數之一之間切換該指針。 C++是否允許這樣做?成員函數指針指向未指定的類類型 - 是否有可能?

+1

函數指針根本不能指向非靜態成員函數,只能將指針指向非靜態成員函數,並且它們具有指定成員類和成員類型的類型。 – 2012-01-17 17:02:01

回答

3

boost::function能夠與boost::bind一起做到這一點:

#incluce <boost/function.hpp> 
#include <boost/bind.hpp> 

struct A{ void f(); }; 
struct B{ void g(); }; 
struct C{ 
    boost::function<void()> _func; 
}; 

int main(){ 
    A a; B b; C c; 
    c.func = boost::bind(&A::f, &a); 
    c.func(); 
    c.func = boost::bind(&B::g, &b); 
    c.func(); 
} 
+0

使用類型擦除和像'std :: function'或'boost :: function'這樣的抽象層實質上給了海報他想要的東西。 – lefticus 2012-01-17 17:37:39

0

不,但你可以讓A和B有一個共同的基類X,然後你可以使用T (X::*)(U...) A和B(假設T和U是相同的)。可以使用boost::variant

1

這是不可能的。當你聲明一個類的成員函數,該函數有一個隱this參數,所以即使你寫void A::func(int i),功能居然有這樣的簽名:

void func(A *const this, int i) 

你會需要像somethign來自Boost.Function和Boost.Bind一起用來做你想做的事情:

boost::function<void (int)> func; 
A* a = new A; 
func = boost::bind(&A::func, a, _1); 
0

不,你不能。

如果可以的話,這是沒有意義的。試想一下,你可以,並且你有一個類型爲A的對象,並且調用一個指向類型B的成員函數的成員函數指針。突然,在B的成員函數中,你將有一個指針指向地址A對象的類型,但類型爲B*。 (這可能是你應該詢問的),但是你可以試着讓所有的類都有一個共同的基本函數(也許是虛擬的)並且使用指針指向這些函數,但是,除非你向我們提供更多細節,否則我們只能猜測。

另一個更廣泛的替代方案可能是使用boost::function對象,這些對象已經綁定到要調用成員函數的對象。

1

當然可以,但你必須刪除一些類型安全和跟蹤這個指針,以及成員函數。

你可以在http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates中看到一個用例。基本思想是將對象指針存儲爲一個void指針,並通過靜態方法重定向函數調用。

#include <iostream> 
using namespace std; 

struct A { void foo() { cout << "A::foo\n"; } }; 
struct B { void foo() { cout << "B::foo\n"; } }; 

class C 
{ 
public: 
    C() : object_ptr(0), stub_ptr(0) {} 

    template <class T, void (T::*TMethod)()> 
    static C from_method(T* object_ptr) 
    { 
     C d; 
     d.object_ptr = object_ptr; 
     d.stub_ptr = &method_stub<T, TMethod>; 
     return d; 
    } 

    void operator()() const 
    { 
     return (*stub_ptr)(object_ptr); 
    } 

private: 
    typedef void (*stub_type)(void* object_ptr); 

    void* object_ptr; 
    stub_type stub_ptr; 

    template <class T, void (T::*TMethod)()> 
    static void method_stub(void* object_ptr) 
    { 
     T* p = static_cast<T*>(object_ptr); 
     return (p->*TMethod)(); 
    } 
}; 

int main() 
{ 
    A a; 
    B b; 

    C c = C::from_method<A, &A::foo>(&a); 

    c(); 

    c = C::from_method<B, &B::foo>(&b); 

    c(); 

    return 0; 
} 

上述代碼應打印

A::foo 
B::foo 

此解決方案比使用std::function,因爲它不要求對數據的堆中分配存儲更快但是這可能僅僅被用來引用的成員函數(不像std::function聲稱任何可調用對象的所有權)。