簡體   English   中英

將成員函數作為參數傳遞給構造函數

[英]Passing a member function as an argument to a constructor

我有一個按鈕課。 我希望按鈕類的構造函數采用按下按鈕時將調用的函數。 如果按鈕類僅從一個類中獲取函數,這將很容易,但是按鈕的構造函數獲取函數的目的是,無論在哪個類中創建按鈕,都將能夠在其中存儲指向函數的指針。創建它的類。

為了顯示:

struct Button {
    Button(void (*functionPtr)()) {
        // Store the function pointer to be called later
    }
};

struct SomeClass {
    void LoadFile();

    SomeClass() {
        Button* temp1 = new Button(&LoadFile); // ???
    }
};

struct AnotherClass {
    void SaveFile();

    SomeClass() {
        Button* temp2 = new Button(&SaveFile); // ???
    }
};

我該如何工作?

盡管看起來很相似,但指向函數的指針和指向成員的函數實際上是完全不同的野獸。

void (*functionPtr)()是指向不帶任何參數並返回void的函數的指針。 &AnotherClass::SaveFile是一個指向AnotherClass 成員函數的AnotherClass ...其類型為void (AnotherClass::*)() 請注意,類名是類型的一部分,因此您不能簡單地將指向成員函數的指針存儲到任意類。 此外,要調用指向成員函數的指針,您需要一個實例指針-您必須以某種方式存儲該指針,但是它們也將具有不同的類型!

在C ++ 11中,您可以做的是使用類型擦除:

std::function<void()> callback;

並為其分配任意可調用項:

template <typename F>
Button(F cb) 
: callback(cb)
{ }

然后可以使用std::bind創建一個按鈕:

Button* temp1 = new Button(std::bind(&OtherClass::LoadFile, this));
Button* temp2 = new Button(std::bind(&AnotherClass::SaveFile, this));

現在, temp1->callback()實際上將在與其一起構造的OtherClass實例上調用LoadFile() 這就是你想要的。 而且,我們仍然可以使用自由功能:

void whatever();
Button* temp3 = new Button(whatever);

插入有關使用原始指針和new的常見警告,並優先使用unique_ptr

您實際上沒有指向成員函數的指針,因為它沒有意義,而沒有隱藏在其上調用對象的this指針。

您可以嘗試解決一些常見的問題。

C方式:

除函數指針外,還存儲一個void* 然后將void* int傳遞給回調。 這不太“安全”,但在C語言中很常見。

OOP方法1:

子類Button並在基類上具有虛函數,例如onPress ,可以在子類中實現。

OOP方法2:

具有獨立於您的自定義類實現的Button的回調接口。

編輯:或使用lambdas如注釋中所述。 我仍在用現代方式重新學習C ++。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM