2011-06-08 90 views
3

我正在查看一些已移植且未能編譯的代碼。代碼已經以類似'C'的方式編寫,並且正在傳遞函數指針以便爲對象設置特定的增變器。被填充的對象聲明如下:將指針傳遞給函數時未知的隱式類型

class Person 
{ 
    std::string n_; 
    int a_; 

    public: 
     void name(const std::string& n) { n_ = n; } 
     std::string name() const { return n_; } 
     void age(const int& a) { a_ = a; } 
     int age() const { return a_; } 
}; 

相當標準的東西。然後我們有我修剪爲簡潔一些有趣的功能:

typedef void (Person::FnSetStr)(const std::string& s); 
typedef void (Person::FnSetInt)(const int& i); 

void setMem(const std::string& label, Person* person, FnSetStr fn) 
{ 
    // Do some stuff to identify a std::string within a message from the label. 
    // assume that 'val_s' contains the string value of the tag denoted by 
    // the label. 
    (person->*fn)(val_s); 
} 

void setMem(const std::string& label, Person* person, FnSetInt fn) 
{ 
    // Do some stuff to identify an int within a message from the label. 
    // assume that 'val_i' contains the int value of the tag denoted by the 
    // label. 
    (person->*fn)(val_i); 
} 

然後調用此方法如下:

Person* person = new Person; 
setMem("Name", person, Person::name); // (1) 
setMem("Age", person, Person::age);  // (2) 

的想法似乎是通過一個標籤,對象和適當的增變器的地址。正在使用第三個參數的類型來讓編譯器選擇要調用的重載,然後特定的重載獲得一個合適的變量就緒,並調用傳遞它的函數作爲參數來設置對象的值。

這處理舊的Solaris編譯器。然而,當它編譯於GCC,我會在點(1)(2)故障:

error: no matching function for call to 
    'setMem(const std::string& label, Person* person, <unknown type>)' 

它看起來像新的編譯器將,比如說,Person::age作爲一個類型,而不是指向一個功能,無法解決超載。我正在改變代碼使用函數對象,而不是直接指向函數。

我想知道是否有一種方法,調用代碼可以保持這種狀態(即沒有明確說明函數所需的類型),因爲我不能更改Person類,並且理想地希望保持最低限度的變化。

回答

5

首先更改聲明:

typedef void (Person::*FnSetStr)(const std::string& s); 
typedef void (Person::*FnSetInt)(const int& i); 

然後改變電話:

setMem("Name", person, &Person::name); // (1) 
setMem("Age", person, &Person::age);  // (2) 

在警告級別4乾淨構建在2010年VS

+0

謝謝你,是的,我得到一個乾淨的構建在GCC 4.1上有這個例子。然而,它不適用於我在GCC 3.2上創建的原始代碼(因爲客戶機密性而重寫),所以GCC變得更好或者有更微妙的事情發生 - 我懷疑後者。 – 2011-06-08 11:35:36