我有一个这样的课程:
class test
{
vector<expr*> _exprs;
bool cmp(expr* e1, expr* e2);
ExprManager* mg;
}
,比较功能是:
bool test::cmp(expr* e1, expr* e2)
{
return exprHight(mg, e1) < exprHight(mg, e2);
}
然后当我使用比较函数对_exprs(在另一个成员函数中)进行排序时
sort(_exprs->begin(), _exprs->end(), cmp);
编译器报告:
error: argument of type ‘bool (test::)(void*, void*)’ does not match ‘bool (test::*)(void*, void*)’
如何解决?谢谢你的进步。
答案 0 :(得分:2)
定义排序谓词的常规方法是作为函子。
让您的班级定义operator()
进行比较,您只需将班级的实例传递给std::sort
。
所以,你需要做的就是定义这样的类:
class test
{
vector<expr*> _exprs;
bool operator()(expr* e1, expr* e2);
ExprManager* mg;
}
然后你可以这样打电话给sort
:
sort(_exprs->begin(), _exprs->end(), test());
或者,当然,使用test
类的现有实例,而不是构建新的实例。但是你只需传入一个类实例,根本不需要提及成员函数。
如果排序发生在另一个成员函数中(从你对_exprs
的引用看起来那样),写一下
sort(_exprs->begin(), _exprs->end(), *this);
需要注意的一点是std::sort
与大多数其他标准库算法一样,复制谓词对象,因此您的谓词类必须能够安全地处理复制(无论如何,您的类应始终执行 )
简而言之,实现这一目标的方法是遵循“三个规则”。
如果你的类定义了析构函数,复制构造函数或赋值运算符,那么它几乎肯定会定义所有三个。
如果使用编译器生成的复制构造函数,它将只复制类的指针成员,因此您将有两个包含指向同一对象的指针的对象。
如果类具有在该指针上调用delete
的析构函数,那么最终会执行两次。这是一个错误。
如果您的类是可复制的(并且大多数标准库都需要这样),那么您必须定义适当的复制构造函数和赋值运算符以安全地实现它(例如,复制指针指向的资源,或者改为使用智能指针。
如果您的类不是可复制的,那么您应该将复制构造函数和赋值运算符定义为private
,以便尝试复制该类将导致编译时间错误,而不是运行时崩溃。
你永远不会定义一个可以复制的类,但是不能正确地这样做。定义必要的复制构造函数/赋值运算符/析构函数以进行处理复制,或通过将复制ctor /赋值运算符设置为私有来进行复制。
在智能指针中包装指向动态分配的内存的指针是一种免费获得可复制性的简单方法。
如果类只包含RAII对象,那么根本不需要定义析构函数,因此规则为3不要求您定义复制构造函数和赋值运算符。
答案 1 :(得分:1)
您需要test::cmp()
静态:
class test {
// ...
static bool cmp( expr * lhs, expr * rhs );
};
或者,如果由于某种原因test::cmp()
无法是静态的,您需要使用(boost::
或std::tr1::
)bind()
绑定{implicit} this
cmp()
参数:
test * someInstance = this // other // something;
sort( _exprs->begin(), _exprs->end(),
bind( &test::cmp, someInstance, _1, _2 ) );
答案 2 :(得分:0)
使用operator()然后将'* this'作为Predicate to Sort算法传递。
class test
{
vector<expr*> _exprs;
bool operator()(expr* e1, expr* e2);
ExprManager* mg;
}
sort(_exprs->begin(), _exprs->end(), *this);
无论你传递什么,因为谓词必须具有公共可访问性,