2011-06-08 46 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