1

我在執行可能不是「傳統」的事情時遇到了C++編譯錯誤。 爲了讓事情變得更簡單,我只是重新編寫了我試圖以易於閱讀的方式使用的機制,並檢查了我遇到了同樣的問題。使用指向類私有方法的指針命名參數成語

的一切都在這裏首先是代碼:

test.h // - - C++ - -

template <typename MODULE> class item; 

template <typename MODULE> 
class init { 
public: 
    typedef int (MODULE::*funcPtr)(int); 
private: 
    funcPtr m_fp; 
public: 
    init& has_funcPtr(funcPtr fp) { m_fp = fp;} 
    init() {} 
    virtual ~init() {} 
private: 
    friend class item<MODULE>; 
}; 

template <typename MODULE> 
class item { 
public: 
    typedef int (MODULE::*funcPtr)(int); 
private: 
    funcPtr m_fp; 
public: 
    item(init<MODULE> params) : m_fp(params.m_fp) {} 
    virtual ~item() {} 
}; 

class user { 
public: 
    typedef init<user>::funcPtr funcPtr; 
private: 
    // Method CB 
    int func1(int i); 
    // Item member 
    item<user> m_item; 
public: 
    user(); 
    virtual ~user(); 
}; 

TEST.CPP // - - C++ - -

#include "test.h" 

user::user() : m_item(init<user>().has_funcPtr(this->func1)) {} 

int user::func1(int i) {return 1;} 

這裏是錯誤:

/test.cpp:5:59: error: invalid use of non-static member function 
user::user() : m_item(init<user>().has_funcPtr(this->func1)) { 
                ^

所以,我不知道這是爲了達到我想要的最好的方式(可能不是,無論如何,如果你有他們非常歡迎其他建議),但現在我的目標是,使工作或正確理解爲什麼它無法工作,所以我從中學到了一些東西!

的基本思想是:

  • 類「項目」可以使用該方法的類「has_funcPtr」命名參數成語被初始化「初始化」串聯到它的構造,如:「INIT( ).has_funcPtr(& function_name)「。
  • 類「用戶」可以一個指向它的私有方法「func1的」存儲類型「項目」的其私有成員的私有成員。

通過這種方式,當調用對象「item」的特定方法時(爲了簡單起見,我不在這裏包含這個長部分,因爲它與錯誤無關,但它只是描述目標這段代碼),該方法可以做的東西,並通過該指針調用其父對象「用戶」的私有方法功能(我希望這是足夠清晰的...)。

現在,我認爲這是與對象的初始化順序的問題,但我不知道在哪裏以及如何解決它。 特別是我認爲既然「func1」方法不對類「user」的任何成員進行操作,那麼它的引用可以直接用在初始化列表中來初始化一個「init」對象並將它提供給一個「項目「對象。

謝謝大家提前

+0

如果將來有人想要重複使用此代碼,則發表評論。在「init」類中的方法「has_funcPtr」中,我忘記了返回對象本身。它應該是: init&has_funcPtr(funcPtr fp){m_fp = fp;返回*這;} – Bertone

回答

4

this->func1沒有形成一個成員函數指針。如果您在user課程中,它應該看起來像&user::func1

+0

謝謝,這是令人難以置信的,我設法鬆了這麼多的時間這麼基本的東西... 但還有一件事。如果我使用&user :: func1,我是否使用指向該實例方法的指針?因爲在開始的時候我只是簡單地把「has_funcPtr(func1)應該工作,因爲我已經在」用戶「範圍內,並且如果我想訪問實例的方法,我應該用某種方式使用這個指針。 – Bertone

+0

成員函數指針沒有綁定到特定的實例,所以當你使用指針時你還需要將它與實例結合起來。請參閱[如何調用指向成員函數?](http://stackoverflow.com /問題/ 1928431 /怎麼辦,我的呼叫一個指針到成員函數) –

0

我在這裏發佈我的問題的完整答案。我在Bo的建議之後開發了它並理解了如何通過指向它的指針指向一個實例特定的方法。

總之,有兩兩件事是非常重要的注意事項:

  1. 一個指向非靜態類的成員函數可以在剛纔的偏移,而不是「絕對地址」被認爲(http://www.codeguru.com/cpp/cpp/article.php/c17401/C-Tutorial-PointertoMember-Function.htm) 。這意味着你不能訪問該函數(它只是一個偏移量),而不需要先創建一個實例指針。一旦你的實例指針,這個「偏移指針」,您可以使用調用該方法:

    (object_ptr->*method_ptr)(parameters_here)

    一個更好的辦法是使用#define宏,因爲這個語法是真的容易出錯,複雜讀(https://isocpp.org/wiki/faq/pointers-to-members):

    #define CALL_MEMBER_FN(ptrToObject,ptrToMember) ((ptrToObject)->*(ptrToMember))

    ,然後用它作爲:

    CALL_MEMBER_FN(object_ptr, method_ptr)(parameters_here)

  2. 繼第一點之後,如果您希望嵌套類能夠通過指向它的指針調用上層類方法,則還需要傳遞上層類實例指針以訪問該函數。在我的情況下,因爲我希望能夠根據情況決定是否應該調用該方法,所以我使用了命名參數成語(下面請注意,func2未註冊例如)。

最後這裏是修改後的代碼,它的作品(測試):

- - C++ - - test.h

#include <iostream> 

template <typename MODULE> class item; 

template <typename MODULE> 
class init { 
public: 
    typedef int (MODULE::*funcPtr)(int); 
    typedef bool (MODULE::*func2Ptr)(bool); 
private: 
    funcPtr m_fp; 
    func2Ptr m_fp2; 
    MODULE* m_dad; 
public: 
    init& has_funcPtr(funcPtr fp) { m_fp = fp; return *this;} 
    init& has_func2Ptr(func2Ptr fp2) { m_fp2 = fp2; return *this;} 
    init(MODULE* dad) : m_dad(dad) { std::cout << "init constructor called\n"; } 
    ~init() {} 
private: 
    friend class item<MODULE>; 
}; 

template <typename MODULE> 
class item { 
public: 
    typedef int (MODULE::*funcPtr)(int); 
    typedef bool (MODULE::*func2Ptr)(bool); 
private: 
    funcPtr m_fp; 
    func2Ptr m_fp2; 
    MODULE* m_dad; 
public: 
    item(init<MODULE> params) : 
    m_fp(params.m_fp), 
    m_fp2(params.m_fp2), 
    m_dad(params.m_dad) 
    { 
    std::cout << "item constructor called\n"; 
    } 
    ~item() {} 
    // Method invoked externally 
    int callback() { 
    std::cout << "item class method callback invoked\n"; 
    // In the real case here do general stuff 
    if(m_fp) { 
     int i = (m_dad->*m_fp)(1); // call member function through its pointer 
     return i; 
    } else { 
     std::cout << "callback not registered\n"; 
     return 0; 
    } 
    } 
    // Method invoked externally 
    bool callback2() { 
    std::cout << "items class method callback2 invoked\n"; 
    // In the real case here do general stuff 
    if(m_fp2) { 
     bool b = (m_dad->*m_fp2)(true); // call member function through its pointer 
     return b; 
    } else { 
     std::cout << "callback2 not registered\n"; 
     return false; 
    } 
    } 
}; 

class user { 
public: 
    typedef init<user>::funcPtr funcPtr; 
private: 
    // Methods that optionally add more functionalities to the 2 callbacks 
    int func1(int i); 
    bool func2(bool b); 
public: 
    // Item member 
    item<user> m_item; 
public: 
    user(); 
    ~user(); 
}; 

- - C++ - - 測試。 cpp

#include "test.h" 

user::user() : m_item(init<user>(this).has_funcPtr(&user::func1)) { 
    std::cout << "user constructor called\n"; 
} 

int user::func1(int i) {return i;} 
bool user::func2(bool b) {return b;} // func2 won't be registered 


int main() { 
    user* u = new user(); 
    // Test callbacks 
    int i = u->m_item.callback(); 
    bool b = u->m_item.callback2(); 
    std::cout << "main is printing i=" << i << " and b=" << b << "\n"; 
    std::cout << "expected results are i=1 and b=0\n" << "END\n"; 
    return 0; 
} 

OUTPUT:

init constructor called 
item constructor called 
user constructor called 
item class method callback invoked 
items class method callback2 invoked 
callback2 not registered 
main is printing i=1 and b=0 
expected results are i=1 and b=0 
END 
相關問題