通常,模板参数可以是抽象类,如下面的程序所示。但似乎比较仿函数必须一定不是抽象的。至少以下版本不能在VC++ 11和Oracle Studio 12上编译。

#include <vector>
#include <algorithm>


class Functor
{
public:
    virtual bool operator()(int a, int b) const = 0;
};


class MyFunctor: public Functor
{
public:
    virtual bool operator()(int a, int b) const { return true; }
};


int _tmain(int argc, _TCHAR* argv[])
{
    vector<Functor> fv; // template of abstract class is possible
    vector<int> v;
    MyFunctor* mf = new MyFunctor();
    sort(v.begin(), v.end(), *mf);
    Functor* f = new MyFunctor();
    // following line does not compile:
    // "Cannot have a parameter of the abstract class Functor"
    sort(v.begin(), v.end(), *f);
    return 0;
}

现在,我想知道这是否是仿函数参数的常规属性,还是取决于STL实现?有什么办法可以得到的,我想做什么?

最佳答案

仿函数通常需要可复制。多态基类通常是不可复制的,抽象基绝不能复制。

更新:感谢@ahenderson和@ltjax的评论,这是一种产生包装对象的简单方法,该包装对象包含原始的多态引用:

#include <functional>

std::sort(v.begin(), v.end(), std::ref(*f));
//                            ^^^^^^^^^^^^
std::ref的结果就是您所需要的std::refrence_wrapper:具有值语义的类,其中包含对原始对象的引用。

仿函数被复制的事实使很多人想在仿函数内部积累一些东西,然后想知道为什么结果不正确。仿函数实际上应该引用一个外部对象。以机智:

不好! 无法按预期工作;仿函数可以任意复制:
struct Func1 {
    int i;
    Func1() : i(0) { }
    void operator()(T const & x) { /* ... */ }
};

Func1 f;
MyAlgo(myContainer, f);

好:您提供累加器;复制仿函数是安全的:
struct Func2 {
   int & i;
   Func2(int & n) : i(n) { }
   void operator()(T const & x) { /* ... */ }
};

int result;
MyAlgo(myContainer, Func2(result));

关于c++ - Functor在C++中永远不可能是抽象的吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12408158/

10-13 07:21