2014-01-06 124 views
-1

我有下面的示例C++程序,它將指針指向類中的方法。調用該方法時出現編譯器錯誤。調用C++方法指針

10  class Foo 
11  { 
12   void set_parm1(string) {} 
13   void set_parm2(string) {} 
14 
15   typedef void (Foo::*set_func_t)(string); 
16   struct Bar 
17   { 
18    string value; 
19    set_func_t set_func; 
20   }; 
21 
22   map<string, Bar> parameter; 
23 
24   public: 
25   Foo(); 
26   void set_value(string key, string value); 
27  }; 
28 
29  Foo::Foo() 
30  { 
31   Bar temp; 
32 
33   temp.value = "value1"; 
34   temp.set_func = &Foo::set_parm1; 
35   parameter["param1"] = temp; 
36 
37   temp.value = "value2"; 
38   temp.set_func = &Foo::set_parm2; 
39   parameter["param1"] = temp; 
40  } 
41 
42  void 
43  Foo::set_value(string key, string value) 
44  { 
45   Bar temp; 
46 
47   temp = parameter[key]; 
48   this->*temp.set_func(value); 
49  } 

問題:

  1. 在行編譯錯誤48

    ./test.cc: In member function 'void Foo::set_value(std::string, std::string)' : ./test.cc:51:35: error: must use '.*' or '->*' to call pointer-to-member function in 'temp.Foo::Bar::set_func (...)' , e.g. '(... ->* temp.Foo::Bar::set_func) (...)'

  2. 我想set_func()(其指向或者set_parm1()set_parm2())在地圖更新的parmX值本身。是否有可能得到地圖參數中存儲的地址Bar.value(第33行)的地址,因此我可以將它傳遞給set_func()

    如果不是,那麼我的下一個選項是什麼,在地圖上存儲指向「Bar」的指針,而不是複製Bar。基本上使用map<string, Bar *>

  3. 只是堅持STL(不使用boost庫),有沒有指導方針來保存一個結構/類的ptr vs存儲在地圖中的整個對象。 (當然這是假設struct/class本身沒有指針,也就是說在存儲整個對象時不需要深度拷貝)。

謝謝
艾哈邁德。

+1

什麼你不只是使用std ::函數和std ::綁定? – PlasmaHH

+0

第48行:刪除* – ipinak

+1

@ipinak並刪除'this->'? –

回答

3

爲1:你需要把它放在括號:

(this->*temp.set_func)(value); 

爲2:你可以採取的temp.value地址(你可能是Bar.value意思?),但因爲它是這將是無用的一個臨時變量,因此該地址在Foo的完成後無效。

對於3:我不太確定你的意思。您可以使用std::shared_ptr et。人。如果你想避免複製大型/昂貴的對象或其他手段,如移動語義來減少開銷,但恐怕沒有一般的答案。

2

@Daniel Frey建議的解決方案可能會起作用。

但是在C++(或其他任何面向對象的語言)中使用它的正確方法是使用多態性。

在技術方面,您需要做的是考慮將繼承與虛函數結合使用,而不是函數指針。

例如(根據你的問題的代碼):

class Foo 
{ 
protected: 
    virtual void set_parm(string)=0; 
    struct Bar 
    { 
     string value; 
    }; 
    map<string, Bar> parameter; 
public: 
    void set_value(string key, string value); 
}; 

class Foo1 : public Foo 
{ 
private: 
    void set_parm(string) {} // you probably wanna do something here... 
public: 
    Foo1(); 
}; 

class Foo2 : public Foo 
{ 
private: 
    void set_parm(string) {} // you probably wanna do something here... 
public: 
    Foo2(); 
}; 

void Foo::set_value(string key, string value) 
{ 
    Bar temp; 
    temp = parameter[key]; 
    set_parm(value); 
} 

Foo1::Foo1() 
{ 
    Bar temp; 
    temp.value = "value1"; 
    parameter["param1"] = temp; 
} 

Foo2::Foo2() 
{ 
    Bar temp; 
    temp.value = "value2"; 
    parameter["param1"] = temp; 
} 
+0

+1注意:我只修復了編譯問題,而不是你好心處理的設計問題,因此upvote :) –