我正在查看已经移植并且无法编译的一些代码。代码以类似“C”的方式编写,并传递函数指针以便在对象上设置特定的mutator。正在填充的对象声明如下:
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)
这个想法似乎是传递一个标签,一个对象和一个适当的mutator的地址。第3个参数的类型用于让编译器选择要调用的重载,然后特定的重载就会获得一个合适的变量,并调用函数将其作为参数传递给对象设置值。
这适用于旧的Solaris编译器。但是,当它在GCC上编译时,我会在(1)
和(2)
点失败:
error: no matching function for call to
'setMem( const std::string& label, Person* person, <unknown type> )'
看起来新编译器将Person::age
视为一种类型而不是指向函数的指针,并且无法解决重载问题。我正在考虑更改代码以使用函数对象而不是直接指向函数。
我想知道调用代码是否可以保持这样的方式(即没有明确说明函数采用的类型),请记住我不能更改Person
类并且会理想情况下,希望将更改保持在最低限度。
答案 0 :(得分: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)
在VS 2010中以警告级别4构建清洁。