2012-01-10 104 views
2

我試圖從派生類傳遞一個函數,它需要一個函數指針的基類函數,但我得到一個編譯器錯誤。無法將派生類函數的指針傳遞到基類

[BCC32 Error] E2034 Cannot convert 'void (Bar::*)(int)' to 'void (Foo::*)(int)' 

我想這是按照設計,但有沒有辦法解決這個不涉及不愉快的鑄造? boost::bind能幫助我嗎?

#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) 

class Foo 
{ 
public: 
    typedef void (Foo::*FFunc)(int i); 

    void test(FFunc f) 
    { 
    CALL_MEMBER_FN(*this,f)(123); 
    } 

    void barf1(int i) {}; 
}; 

class Bar : public Foo 
{ 
public: 
    void barf2(int i) {}; 
}; 

void ffff() 
{ 
    Foo f; 
    f.test(Foo::barf1); // works 

    Bar b; 
    b.test(Bar::barf1); // works 
    b.test(Bar::barf2); // ERROR 
} 

作爲一個方面說明,我這工作正常使用虛擬函數,這是顯而易見的方法,而不是一個函數指針,但我只是想獲得它在嘗試一些刺激前的工作是這樣的: :綁定掛羊頭賣狗肉後...

+0

如果你有一個C++編譯器11,也許你可以使用[' std :: function'](http://en.cppreference.com/w/cpp/utility/functional/function)和['std :: bind'](http://en.cppreference.com/w/ CPP /實用程序/功能/綁定)? – 2012-01-10 13:12:46

回答

1

b.test((Foo::FFunc)&Bar::barf2);

對不起,不是故意要提交的答案,想發表評論。 Sample code

編輯:嗯,也許這是更令人愉快的鑄造,因爲它是C++風格? Updated sample.

b.test(static_cast<Foo::FFunc>(&Bar::barf2));

+0

嗯,這是有效的。但這是我希望避免的「不愉快的投射」! – Roddy 2012-01-10 13:32:54

+0

@Roddy你可以使用'static_cast',這是完全有效的C++強制轉換。我的意思是,我敢打賭'boost :: bind'在內部的某個地方使用這種類型的東西... – lapk 2012-01-10 13:38:08

+0

你確定這是有效的C++嗎?從我記得將一個函數(或成員函數)指針轉換爲另一種類型然後嘗試調用它是非法的。它可能在這種情況下工作,因爲從'b'到'Foo *'(調用'test'時)可能是noop,但我認爲這是不能保證的(如果多重或虛擬繼承是參與)。 – Grizzly 2012-01-10 14:13:57

1

此外,正如我的C++ 11 & &博斯特的知識& & STL是不是最好的,我只能勸這樣的:

template <typename T> 
    void test(void (T::*f)(int)) 
    { 
    CALL_MEMBER_FN(static_cast<T&>(*this),f)(123); 
    } 

所有其他代碼相同,以你的。

壞鑄造,但它隱藏

1

你可以概括函數指針多一點?我的意思是這樣的:

typedef void (Foo::*FFunc)(int i); 

到:

typedef void (*FFunc)(int i); 

然後你可以使用綁定:

b.test(bind(&Bar::barf2, &b)); 
+1

不,你不能從'綁定'(我假設你的意思是'boost :: bind'或'std :: bind',否則請詳細說明)返回一個函數對象而不是函數指針。 'typedef函數 FFunc;'應該可以工作(但當然有很多開銷)。 ' – Grizzly 2012-01-10 14:09:30

+0

你說得對,我的錯。我使用boost:函數,而不是函數指針。綁定將不會與指針一起使用。 – 2012-01-10 14:11:13

相關問題