2012-03-05 85 views
1

我需要计算指针数组的对象与赋予成员函数的参数具有相同名称(成员变量)的次数。我尝试过不同的方法,但都没有工作。我的代码甚至没有编译。错误是:“错误C2514:'MyComparator':类没有构造函数”,这里是我用于比较和用于计算协议的函数的类的代码。在对象指针向量中使用STL算法(C++)

//definition of the vector 
vector<Class1*> files; 
... 
int Class2::countNames(string name) 
    { 
     return count_if(files.begin(), files.end(), bind2nd(MyComparator(),name)); 
    } 
... 
class MyComparator{ 
public: 
bool operator()(const CFileType*& ob1, const string &str) 
{ 
    return ob1->getName()==str; 
} 
}; 

我很困难这个好几个小时,我想用STL来做。这里的问题是我有一个指针向量,如果我有一个正常的向量它不需要谓词函数,在我的情况下,我必须给它一个参数,我认为bind2nd()是正确的方法。任何帮助将不胜感激!

回答

1

在C++ 11下,您可以使用lambda表达式,这比旧式的bind2nd容易得多。例如:

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

class Class1 { 
public: 
    Class1(const std::string& name) : Name(name) { 
    } 
    const std::string& getName() const { 
     return Name; 
    } 
private: 
    std::string Name; 
}; 

size_t CountMatchingNames(const std::vector<Class1*>& v, const std::string& name) { 
    return std::count_if(
     v.begin(), 
     v.end(), 
     [&name](Class1* c1) { return name == c1->getName(); } 
    ); 
} 

int main() { 

    Class1 rob("rob"); 
    Class1 bob("bob"); 
    Class1 mitch("mitch"); 

    std::vector<Class1*> v; 
    v.push_back(&bob); 
    v.push_back(&mitch); 
    v.push_back(&rob); 
    v.push_back(&mitch); 
    v.push_back(&bob); 
    v.push_back(&bob); 

    std::cout << "rob count:\t" << CountMatchingNames(v, "rob") << std::endl; 
    std::cout << "bob count:\t" << CountMatchingNames(v, "bob") << std::endl; 
    std::cout << "mitch count:\t" << CountMatchingNames(v, "mitch") << std::endl; 

    return EXIT_SUCCESS; 

} 

此打印:

rob count:  1 
bob count:  3 
mitch count: 2 
+0

非常感谢,它工作完美,它比使用** bold ** bind2nd()**更加紧凑** bold ** – Goshutu 2012-03-06 10:35:04

+0

@Goshutu我忘记了通过引用传递向量(请参阅编辑) 。这不会影响正确性,但会影响性能,因为每次调用“CountMatchingNames”时不再需要复制向量。 – 2012-03-06 10:59:40

+0

没有问题,因为这是一个类的成员函数 – Goshutu 2012-03-06 17:46:14

1

首先,你需要确保,当你使用它的比较级是可以确定的:在前面定义的移动MyComparator定义countNames()将是我的第一步。也就是说,bind2nd()想知道它所处理的函数对象比你提供的要好一些:它通常想知道result_typefirst_argument_typesecond_argument_type。你可以从std::binary_function<bool, CFileType const*, std::string const&>或明确定义它们。虽然我不认为这是必需的,但您可能需要使函数调用运算符const。另一方面,如果你正在定义一个函数对象而不是一个函数(你可以使用std::ptr_fun()来获得必要的typedef;个人而言,我认为这个名字的意思是让这些人有吸引力,因为它肯定不是很多有趣当你不得不使用它们),你可以去整个的方式,而不是用在首位粘合剂争战

class MyComparator { 
public: 
    MyComparator(std::string const& value): value_(value) {} 
    bool operator()(CFileType const* obj) const { 
     return obj->getName() == this->value_; 
    } 
private: 
    std::string value_; 
}; 
... 
std::count_if(files.begin(), files.end(), MyComparator(name)); 

您可以定义一个函数,并结合其在使用粘合剂得到大致相同的效果。 Typeically,我做错了,当我不尝试一下代码,但它会是这个样子:

bool myComparator(CFileType const* obj, std::string name) { 
    return obj->getName() == name; 
} 
... 
std::count_if(files.begin(), files.end(), 
       std::bind2nd(std::ptr_fun(myComparator), name)); 

如果你觉得你想通过引用传递的参数name而不是复制这一切的时候,您将无法使用std::bind2nd(),至少除非您使用C++ 2011编译器:否则它将创建一个类型,该类型必须连续编译器不会喜欢的const关键字。您可以使用例如boost::bind()不存在这个问题:

std::count_if(files.begin(), files.end(), boost::bind(myComparator, _1, name)); 

...并改变name参数的声明是std::string const& name

1

您在这里有几个问题:

  • 它看起来像你使用它后确定MyComparator。类型需要在使用前定义。
  • 矢量包含Class1*,但比较器适用于CFileType*
  • 过时的bind1stbind2nd使用起来有点棘手,并且要求函数类型定义各种类型。假设你不能使用新的std::bind(或boost::bind),最简单的方法来解决这个问题是MyComparatorstd::binary_function<Class1*, string, bool>
  • operator()需要声明const继承。

如果你的编译器支持C++ 11,那么你可以写这更简单地使用或者std::bind或λ:

count_if(files.begin(), files.end(), bind(MyComparator(), placeholders::_1, name)); 

count_if(files.begin(), files.end(), [&name](Class1 const * p){return p->getName()==name;}); 
1

原则的思想工作,但是:

  1. 比较器类必须在使用之前进行定义;
  2. 它必须继承binary_function以包含必要的typedef;
  3. operator()需要声明const

通过这些修正,下面的例子为我工作:

#include <vector> 
#include <functional> 
#include <string> 
#include <algorithm> 
#include <iostream> 

using namespace std; 

struct Class1 { 
    string getName() const { return "aaa"; } 
}; 

//... 
class MyComparator: public binary_function<const Class1*, string, bool> { 
public: 
bool operator()(const Class1* ob1, const string &str) const 
{ 
    return ob1->getName()==str; 
} 
}; 

vector<Class1*> files; 
//... 
int countNames(string name) 
    { 
     return count_if(files.begin(), files.end(), bind2nd(MyComparator(),name)); 
    } 

int main() { 
    files.push_back(new Class1); 
    files.push_back(new Class1); 
    cout << countNames("aaa") << ' ' << countNames("bbb") << endl; 
} 

但是请注意,具有指针的矢量容易导致内存泄漏(如在我的例子)。考虑使用Boost.PointerContainer或(使用C++ 11)unique_ptr的容器。

+0

我已经试过这种方法,它没有工作,出来了相同的错误消息,虽然,“Branko Dimitrijevic”的答案工作,我的程序运行现在好! – Goshutu 2012-03-06 10:32:26