2013-07-11 48 views
5

正如標題所示,我在基於類的C++結構中實現OpenCV的mouseCallback函數時遇到了一些麻煩。請允許我解釋一下。我定義了一個名爲BriskMatching的類,其中我使用OpenCV需要的正確參數(請參閱下面的代碼片段)創建了一個名爲mouseCallback的成員函數。無法創建基於類的OpenCV的mouseCallback函數的實現

**Briskmatching.h** 

class BriskMatching 
{ 
public: 
    BriskMatching(); 
    ~BriskMatching(); 

public: 
    void mouseCallback(int event, int x, int y, int flags, void *param); 
}; 

這是所有罰款,但是當我嘗試設置此功能通過OpenCV的的cv::setMouseCallback功能指定的鼠標回調函數我的問題出現了。

在我的主要功能,我創建一個名爲briskMatcher然後當談到時間設置鼠標回調我試圖做這樣的...

cv::setMouseCallback("Matches", BriskMatching::mouseCallback, &matchesImg); 

不幸的是,這將引發的BriskMatching類的一個實例一個錯誤。

Error 3 error C3867: 'BriskMatching::mouseCallback': function call missing argument list; use '&BriskMatching::mouseCallback' to create a pointer to member c:\users\mobilef\documents\visual studio 2010\projects\opencv_objtracking\opencv_briskmatching\main.cpp 54 1 OpenCV_BriskMatching 

我可以聲明mouseCallback功能staticBriskMatching.h但後來我得到其他錯誤的整體失衡,因爲我指的是很多非靜態成員變量在mouseCallback功能擺脫這種錯誤的。

所以我對你們的問題是這樣的。我應該如何修改我的代碼,以便能夠正確地將在BriskMatching類中聲明的mouseCallback函數傳遞給cv::setMouseCallback函數?

感謝您的高級幫助!

回答

12

由於成員函數需要this指針,因此您需要一個靜態包裝函數。通常情況下,你使用param參數是成員函數屬於對象的地址,所以你最終的東西是這樣的:

... 
static void mouseCallback(int event, int x, int y, int flags, void *param); 

void doMouseCallback(int event, int x, int y, int flags); 

然後是mouseCallback內:

void BriskMatching::mouseCallback(int event, int x, int y, int flags, void *param) 
{ 
    BriskMatching *self = static_cast<BriskMatching*>(param); 
    self->doMouseCallback(event, x, y, flags); 
} 
+0

完美,謝謝!它很好用,但我不完全理解它背後的邏輯或它的工作原理。我已經使用C++編寫了幾年,但我一直避免使用類型轉換,所以對我來說它總是有點灰色地帶。我現在要去閱讀它們,並試圖瞭解這一切如何運作。 – szakeri

0

我也在使用這種方法,但是我意識到,靜態助手類是相當嚴格的,類型和方法綁定。

只是爲了進一步參考我已經定義了一個模板免費功能,看起來像:

template<typename TClass, void (TClass::*MouseClickType)(int, int, int, int)> 
void FreeOnMouseCallback(int event, int x, int y, int flags, void* ptr) 
{ 
    auto* mcPtr = static_cast<TClass*>(ptr); 
    if(mcPtr != NULL) 
    { 
     (mcPtr->*MouseClickType)(event, x, y, flags); 
    } 
} 

現在我可以調用內部類任意函數(簽名匹配,而不是名稱)與

cv::setMouseCallback(WindowName, FreeOnMouseCallback<Calibrator, &Calibrator::OnMouseCallback>, this); 

如果還需要void * ptr,它可能會被擴展,但我在這裏省略了它。