通常,模板参数可以是抽象类,如下面的程序也显示.但似乎排序中的比较仿函数不能是抽象的.至少以下内容无法使用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(),*f); return 0; }
现在,我想知道这是否是函子参数的一般属性,还是它依赖于STL实现?有办法获得,我想做什么?
解决方法
函数通常需要是可复制的.多态基类通常不可复制,而抽象基类从不可复制.
更新:感谢@ahenderson和@ltjax的评论,这里有一个非常简单的方法来生成一个保存原始多态引用的包装器对象:
#include <functional> std::sort(v.begin(),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));