将指针传递给函数时隐式类型未知

时间:2011-06-08 10:57:57

标签: c++ function pointers

我正在查看已经移植并且无法编译的一些代码。代码以类似“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类并且会理想情况下,希望将更改保持在最低限度。

1 个答案:

答案 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构建清洁。