指向成员函数的指针
我试图将函数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;
}
这里是你想要的方式的语法:
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);
感谢您指出使用(* it)不是 - >这非常有帮助。 – Anand 2012-03-08 16:25:26
的成员函数需要一个指向对象实例。也就是说,想想getX
为string 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;
}
这是有效的。我的解决方案快一点:p(在运行时)。你应该提到'#include
通过绑定,可以使用更多普通的'Row'成员。例如。那些有额外参数的人。 – devil 2012-03-08 04:06:25
下面是如何使用指针的成员函数来做到这一点:
// 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>("");
请记住它会为'GetX'和'GetY'创建'Table :: filter'的单独副本。我认为OP不希望单独复制(编译时间),而是在运行时进行评估。 – iammilind 2012-03-08 04:11:53
@iammilind嗯,真的,它复制了生成的代码,但是,如果编译器完成了它的工作,那么通过少一次加法和(可能)内联就可以加快调用速度。总的来说,这可能并不重要,反正它不像函数那么大。 – 2012-03-08 04:19:32
如果你想使用显式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;
}
};
这里修改代码:
这里:
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);
...
感谢您的所有答案。我选择了其中的一个作为答案,不幸的是我无法检查所有答案。对于那个很抱歉。 – Anand 2012-03-08 16:32:19