這是一個簡單的問題,但答案非常複雜。簡短的答案是你可以做你想用std :: bind1st或boost :: bind做的事情。較長的答案在下面。
編譯器無誤建議您使用& CLoggersInfra :: RedundencyManagerCallBack。首先,如果RedundencyManagerCallBack是成員函數,則函數本身不屬於類CLoggersInfra的任何特定實例。它屬於類本身。如果你之前曾經調用過一個靜態類函數,你可能會注意到你使用了相同的SomeClass :: SomeMemberFunction語法。由於函數本身是屬於類而不是特定實例的「靜態」,因此您使用相同的語法。 '&'是必要的,因爲從技術上講,你不直接傳遞函數 - 函數不是C++中的真實對象。而是在技術上傳遞函數的內存地址,即指向函數指令在內存中的起始位置的指針。但結果是一樣的,你有效地'傳遞函數'作爲參數。
但在這種情況下,這只是問題的一半。正如我所說的,RedundencyManagerCallBack函數不屬於任何特定的實例。但是這聽起來像是你想把它作爲一個回調與一個特定的實例考慮在一起。要理解如何做到這一點,您需要了解成員函數的真正含義:常規未定義的任何類函數帶有額外的隱藏參數。
例如:
class A {
public:
A() : data(0) {}
void foo(int addToData) { this->data += addToData; }
int data;
};
...
A an_a_object;
an_a_object.foo(5);
A::foo(&an_a_object, 5); // This is the same as the line above!
std::cout
多少參數時A :: foo的需要?通常情況下,我們會說1.但引導下,foo真的需要2個。考慮A :: foo的定義,它需要一個特定的A實例,以使'this'指針有意義(編譯器需要知道'這是)。通常,通過語法MyObject.MyMemberFunction()來指定要「this」的方式。但是這只是用於將MyObject的地址作爲MyMemberFunction的第一個參數傳遞的語法糖。同樣,當我們在類定義中聲明成員函數時,我們不會將'this'放入參數列表中,但這僅僅是語言設計者爲保存輸入而提供的禮物。相反,你必須指定一個成員函數是靜態的,以便自動退出它以獲得額外的'this'參數。如果C++編譯器編譯上面的例子C代碼(原來的C++編譯器實際工作這種方式),它可能會寫這樣的事:
struct A {
int data;
};
void a_init(A* to_init)
{
to_init->data = 0;
}
void a_foo(A* this, int addToData)
{
this->data += addToData;
}
...
A an_a_object;
a_init(0); // Before constructor call was implicit
a_foo(&an_a_object, 5); // Used to be an_a_object.foo(5);
回到你的榜樣,現在有一個明顯的問題。 'Init'需要一個指向一個參數的函數的指針。但是& CLoggersInfra :: RedundencyManagerCallBack是一個函數的指針,它接受兩個參數,它是普通參數和祕密'this'參數。因此,爲什麼你仍然得到一個編譯器錯誤(作爲一個方面說明:如果你曾經使用Python,這種混淆是爲什麼所有成員函數都需要'self'參數)。
處理這個問題的詳細方法是創建一個特殊對象,該對象包含一個指向您想要的實例的指針,並且具有一個名爲「run」或「execute」(或重載'()'操作符)的成員函數)它接受成員函數的參數,並簡單地使用存儲實例上的這些參數調用成員函數。但是這需要你改變'Init'來取你的特殊對象而不是一個原始的函數指針,而且聽起來像Init是別人的代碼。每次出現這個問題時都要做一個特殊的課程,這會導致代碼膨脹。
所以,現在,終於,很好的解決方案,提高::綁定和boost ::功能,每個的文檔,你可以在這裏找到:
boost::bind docs, boost::function docs
的boost ::綁定將讓你需要一個函數和該函數的一個參數,並在該參數被鎖定的地方創建一個新函數。所以,如果我有一個函數添加兩個整數,我可以使用boost :: bind來創建一個新的函數,其中一個參數被鎖定爲5,這個新函數只需要一個整數參數,並且總是會添加5個到它。使用這種技術,您可以將隱藏的'this'參數鎖定爲特定的類實例,並生成一個只需要一個參數的新函數,就像您想要的那樣(請注意,隱藏參數始終是第一個參數,正常參數按順序排列)。看看boost :: bind docs的例子,他們甚至專門討論瞭如何將它用於成員函數。從技術上講,有一個稱爲std :: bind1st的標準函數,你也可以使用,但boost :: bind更通用。
當然,只有一個捕獲。 boost :: bind將會爲你提供一個很好的boost :: function,但是這在技術上仍然不像Init可能需要的原始函數指針。值得慶幸的是,boost提供了一種將boost :: function轉換爲raw指針的方法,如StackOverflow here中所記錄。它如何實現這個超出了這個答案的範圍,儘管它也很有趣。
不要擔心,如果這看起來很可笑 - 你的問題與C++的幾個較暗的角相交,而且boost :: bind一旦學習它就會非常有用。
該鏈接現在是https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr;看起來他現在說「不要」。這就是爲什麼只有鏈接的答案不好。 – 2016-01-12 19:45:11
隨意編輯我八歲的答案:-) – 2016-01-12 22:06:25