2012-03-08 132 views
3

我试图将函数filterX()filterY()推广到以下class Table函数filter()指向成员函数的指针

功能filterX()filterY()仅在程序中调用的函数不同。 filterX()调用getX()filterY()调用getY()

#include <iostream> 
#include <string> 
#include <vector> 

using namespace std; 

class Row 
{ 
    public: 
     void add(string x, string y, int val); 
     string getX() const { return d_x; } 
     string getY() const { return d_y; } 
     int getVal() const { return d_val; } 

    private: 
     string d_x; 
     string d_y; 
     int d_val; 
}; 

class Table 
{ 
    public: 
     void add(string x, string y, int val); 
     vector<int> filterX(string s); 
     vector<int> filterY(string s); 
    private: 
     vector<Row> d_table; 
}; 


//--------------------class Row---------------------------- 
void Row::add(string x, string y, int val) 
{ 
    d_x = x; 
    d_y = y; 
    d_val = val; 
} 


//-------------------class Table--------------------------- 

void Table::add(string x, string y, int val) 
{ 
    Row r; 
    r.add(x, y, val); 
    d_table.push_back(r); 
} 

vector<int> Table::filterX(string s) 
{ 
    vector<int> result; 
    vector<Row>::iterator it; 
    for(it = d_table.begin(); it != d_table.end(); ++it) { 
     if(it->getX() == s) { 
      int val = it->getVal(); 
      result.push_back(val); 
     } 
    } 
    return result; 
} 


vector<int> Table::filterY(string s) 
{ 
    vector<int> result; 
    vector<Row>::iterator it; 
    for(it = d_table.begin(); it != d_table.end(); ++it) { 
     if(it->getY() == s) { 
      int val = it->getVal(); 
      result.push_back(val); 
     } 
    } 
    return result; 
} 

int main() 
{ 
    Table t; 
    t.add("x1", "y1", 1); 
    t.add("x1", "y2", 2); 
    t.add("x2", "y1", 3); 
    t.add("x2", "y2", 4); 

    vector<int> vx = t.filterX("x1"); 
    vector<int> vy = t.filterY("y2"); 

    vector<int>::const_iterator it; 

    cout << "Matching X" << endl; 
    for(it = vx.begin(); it != vx.end(); ++it) 
     cout << *it << "\t"; 
    cout << endl; 

    cout << "Matching Y" << endl; 
    for(it = vy.begin(); it != vy.end(); ++it) 
     cout << *it << "\t"; 
    cout << endl; 

    return 0; 
} 

我试过指向成员函数的指针,但因编译器错误而陷入困境。对于下面的例子,我想有以下main()如果这是可能的:

int main() 
{ 
    Table t; 
    t.add("x1", "y1", 1); 
    t.add("x1", "y2", 2); 
    t.add("x2", "y1", 3); 
    t.add("x2", "y2", 4); 

    // instead of filterX, need to pass getX 
    // to a function named filter  
    vector<int> vx = t.filter("x1", getX); 
    vector<int> vy = t.filter("y2", getY); 

    return 0; 
} 
+0

感谢您的所有答案。我选择了其中的一个作为答案,不幸的是我无法检查所有答案。对于那个很抱歉。 – Anand 2012-03-08 16:32:19

回答

1

这里是你想要的方式的语法:

vector<int> Table::filter(string s, string (Row::*get)() const) 
{         //^^^^^^^^^^^^^^^^^^^^^^^^^^^ member pointer 
    ... 
    if(((*it).*get)() == s) { // call using the (*it). and not it-> 
    ... 
} 

称其为:

vector<int> vx = t.filter("x1", &Row::getX); 
vector<int> vy = t.filter("y2", &Row::getY); 
+0

感谢您指出使用(* it)不是 - >这非常有帮助。 – Anand 2012-03-08 16:25:26

2

的成员函数需要一个指向对象实例。也就是说,想想getXstring Row::getX(const Table *this)。您需要将bind成员函数与实例占位符一起使用。

E.g.使用TR1,

vector<int> vx = t.filter("x1", std::bind(&Row::getX, std::placeholders::_1)); 

的结合创建了一个算符,它接受一个对象,假设你的滤波器功能正确定义。您应该显示代码filter。我相信它应该是:

template <class function> 
vector<int> Table::filter(const string &s, function f) 
{ 
    vector<int> result; 
    for (vector<Row>::const_iterator it = d_table.begin(), tEnd = d_table.end(); 
     it != tEnd; ++it) 
    { 
     if (s == f(*it)) result.push_back(it->getVal()); 
    } 
    return result; 
} 
+0

这是有效的。我的解决方案快一点:p(在运行时)。你应该提到'#include '。 – 2012-03-08 04:02:51

+0

通过绑定,可以使用更多普通的'Row'成员。例如。那些有额外参数的人。 – devil 2012-03-08 04:06:25

1

下面是如何使用指针的成员函数来做到这一点:

// helper to avoid type nightmare; 
typedef string (Row::* GetterP)() const; 

class Table 
{ 
public: 
    void add(string x, string y, int val); 

    // Define a templated function that can be called with GetX or GetY 
    template <GetterP getter> 
    vector<int> filter(string s) 
    { 
     int i = (d_table[i].*getter)(); // how to use getter in filter 
    } 

private: 
    vector<Row> d_table; 
}; 

// Usage: 
Table t; 
t.filter<&Row::GetX>(""); 
+0

请记住它会为'GetX'和'GetY'创建'Table :: filter'的单独副本。我认为OP不希望单独复制(编译时间),而是在运行时进行评估。 – iammilind 2012-03-08 04:11:53

+0

@iammilind嗯,真的,它复制了生成的代码,但是,如果编译器完成了它的工作,那么通过少一次加法和(可能)内联就可以加快调用速度。总的来说,这可能并不重要,反正它不像函数那么大。 – 2012-03-08 04:19:32

1

如果你想使用显式PMF(或者至少看看他们是如何使用的) :

声明PMF类型:

class Row 
{ 
    public: 
    typedef string (Row::*getFilter)() const; 
    // etc. 
}; 

class Table 
{ 
    public: 
    // Call it like this: 

    vector<int> pmf_filterX(string s) 
    { 
     return filter(s, &Row::getX); 
    } 
    private: 
    // Use it like this: 
    vector<int> filter(string s, Row::getFilter f) 
    { 
     vector<int> result; 
     vector<Row>::iterator it; 
     for(it = d_table.begin(); it != d_table.end(); ++it) 
      { 
      const Row& row = *it; 

      if ((row.*f)() == s) 
       { 
       int val = it->getVal(); 
       result.push_back(val); 
       } 
      } 
     return result; 
    } 
}; 
1

这里修改代码:

​​

这里:

vector<int> Table::filter(string s, string (Row::*f)() const) 
{ 
    vector<int> result; 
    vector<Row>::iterator it; 
    for(it = d_table.begin(); it != d_table.end(); ++it) { 
     if((*it.*f)() == s) { 
      int val = it->getVal(); 
      result.push_back(val); 
     } 
    } 
    return result; 
} 

在这里:

int main() 
{ 
    ... 
    vector<int> vx = t.filter("x1", &Row::getX); 
    vector<int> vy = t.filter("y2", &Row::getY); 

    ...