1

我需要计算指针数组的对象与赋予成员函数的参数具有相同名称(成员变量)的次数。我尝试了不同的方法,但都没有奏效。我的代码甚至没有编译。错误是:“错误 C2514:'MyComparator':类没有构造函数”,这是我用于比较的类的代码和用于计算并发的函数。

 //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() 是正确的方法。任何帮助将不胜感激!

4

4 回答 4

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
于 2012-03-06T00:08:24.303 回答
1

首先,您需要确保在使用比较类时知道它:将定义移到定义MyComparator前面countNames()是我的第一步。也就是说,bind2nd()它想知道它处理的函数对象比你提供的要好一点:它通常想知道result_typefirst_argument_typesecond_argument_type。您可以通过 fromstd::binary_function<bool, CFileType const*, std::string const&>或通过显式定义它们来获取它们。尽管我认为这不是必需的,但您可能希望使函数调用 operator const。另一方面,如果你定义的是一个函数对象而不是一个函数(你可以得到必要typedef的 s using std::ptr_fun(); 我个人认为这个名字是为了让这些人有吸引力,因为它肯定不是很多当你必须使用它们时很有趣),你可以一直走下去,而不是一开始就干涉活页夹:

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));

在定义函数并绑定它时,您可以使用绑定器获得大致相同的效果。通常,当我不尝试代码时会出错,但它看起来像这样:

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()不存在此问题的 eg:

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

...并将name参数的声明更改为std::string const& name.

于 2012-03-06T00:11:34.257 回答
1

你在这里有几个问题:

  • 看起来你是MyComparator在使用它之后定义的。使用前需要定义类型。
  • 向量包含Class1*,但比较器与 一起使用CFileType*
  • 不推荐使用bind1st并且bind2nd使用起来有点棘手,并且需要通过函数类型定义各种类型。假设您不能使用新的std::bind(或boost::bind),最简单的解决方法是MyComparator继承自std::binary_function<Class1*, string, bool>
  • operator()需要声明的const

如果您的编译器支持 C++11,那么您可以更简单地使用std::bindlambda 或 lambda 来编写:

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;});
于 2012-03-06T00:14:17.440 回答
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)s 的容器unique_ptr

于 2012-03-06T00:22:53.580 回答