尝试编译以下代码时出现编译错误,我该怎么办?
ISO C++ 禁止获取地址 不合格的或带括号的 非静态成员函数形成 指向成员函数的指针。
class MyClass {
int * arr;
// other member variables
MyClass() { arr = new int[someSize]; }
doCompare( const int & i1, const int & i2 ) { // use some member variables }
doSort() { std::sort(arr,arr+someSize, &doCompare); }
};
doCompare
必须是static
。如果 doCompare
需要来自 MyClass
的数据,您可以通过以下更改将 MyClass
转换为比较函子:
doCompare( const int & i1, const int & i2 ) { // use some member variables }
进入
bool operator () ( const int & i1, const int & i2 ) { // use some member variables }
并致电:
doSort() { std::sort(arr, arr+someSize, *this); }
还有,
doSort
不是缺少返回值吗?
我认为应该可以使用
std::mem_fun
和某种绑定将成员函数变成自由函数,但目前我无法理解确切的语法。
编辑:Doh,
std::sort
按值获取函数,这可能是一个问题。为了解决这个问题,请将函数包装在类中:
class MyClass {
struct Less {
Less(const MyClass& c) : myClass(c) {}
bool operator () ( const int & i1, const int & i2 ) {// use 'myClass'}
MyClass& myClass;
};
doSort() { std::sort(arr, arr+someSize, Less(*this)); }
}
正如 Andreas Brinck 所说,doCompare 必须是静态的 (+1)。如果您必须在比较器函数中拥有一个状态(使用类的其他成员),那么您最好使用仿函数而不是函数(这样会更快):
class MyClass{
// ...
struct doCompare
{
doCompare( const MyClass& info ) : m_info(info) { } // only if you really need the object state
const MyClass& m_info;
bool operator()( const int & i1, const int & i2 )
{
// comparison code using m_info
}
};
doSort()
{ std::sort( arr, arr+someSize, doCompare(*this) ); }
};
使用函子总是更好,只是输入时间更长(这可能不方便,但哦好吧......)
我认为您也可以将 std::bind 与成员函数一起使用,但我不确定如何使用,而且无论如何这都不容易阅读。
2014 年更新:今天我们可以使用 c++11 编译器,因此您可以使用 lambda,代码会更短,但具有完全相同的语义。
Rob 提出的解决方案现在是有效的 C++11(不需要 Boost):
void doSort()
{
using namespace std::placeholders;
std::sort(arr, arr+someSize, std::bind(&MyClass::doCompare, this, _1, _2));
}
确实,正如 Klaim 所提到的,lambda 是一种选择,但有点冗长(你必须“重复”参数是整数):
void doSort()
{
std::sort(arr, arr+someSize, [this](int l, int r) {return doCompare(l, r); });
}
C++14在这里支持
auto
:
void doSort()
{
std::sort(arr, arr+someSize, [this](auto l, auto r) {return doCompare(l, r); });
}
但是,您仍然声明参数是通过副本传递的。
那么问题就是“哪个效率最高”。 Travis Gockel 处理了这个问题:Lambda 与 Bind。他的基准测试程序在我的电脑上给出(OS X i7)
Clang 3.5 GCC 4.9
lambda 1001 7000
bind 3716166405 2530142000
bound lambda 2438421993 1700834000
boost bind 2925777511 2529615000
boost bound lambda 2420710412 1683458000
其中
lambda
是直接使用的 lambda,lambda bound
是存储在 std::function
中的 lambda。
因此看来 lambda 是一个更好的选择,这并不奇怪,因为编译器提供了可以从中获利的更高级别信息。
boost::bind
:
void doSort() {
std::sort(arr,arr+someSize, boost::bind(&MyClass::doCompare, this, _1, _2));
}
有一种方法可以做你想做的事,但你需要使用一个小适配器。由于STL不给你写,可以自己写:
template <class Base, class T>
struct adaptor_t
{
typedef bool (Base::*method_t)(const T& t1, const T& t2));
adaptor_t(Base* b, method_t m)
: base(b), method(m)
{}
adaptor_t(const adaptor_t& copy) : base(copy.base), method(copy.method) {}
bool operator()(const T& t1, const T& t2) const {
return (base->*method)(t1, t2);
}
Base *base;
method_t method;
}
template <class Base, class T>
adaptor_t<Base,T> adapt_method(Base* b, typename adaptor_t<Base,T>::method_t m)
{ return adaptor_t<Base,T>(b,m); }
然后就可以使用它了:
doSort() { std::sort(arr,arr+someSize, adapt_method(this, &doCompare)); }
只需将辅助函数设置为静态,您将在排序函数中传递该函数。
例如
struct Item
{
int val;
int id;
};
//Compare function for our Item struct
static bool compare(Item a, Item b)
{
return b.val>a.val;
}
现在您可以将其传递到排序函数中
有效使用成员函数的一个非常简单的方法是使用运算符<. That is, if you have a function called compare, you can call it from operator<. Here is a working example:
class Qaz
{
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const
{
return compare(*this,aOther);
}
static bool compare(const Qaz& aP,const Qaz& aQ)
{
return aP.x < aQ.x;
}
int x;
};
那么你甚至不需要将函数名赋予 std::sort:
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
更新 Graham Asher 答案,因为您不需要比较,但可以直接使用 less 运算符。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Qaz {
public:
Qaz(int aX): x(aX) { }
bool operator<(const Qaz& aOther) const {
return x < aOther.x;
}
int x;
};
int main() {
std::vector<Qaz> q;
q.emplace_back(8);
q.emplace_back(1);
q.emplace_back(4);
q.emplace_back(7);
q.emplace_back(6);
q.emplace_back(0);
q.emplace_back(3);
std::sort(q.begin(),q.end());
for (auto& num : q)
std::cout << num.x << "\n";
char c;
std::cin >> c;
return 0;
}
有人可以举一个例子,其中比较函数用于设置。例如
#include <map>
#include <set>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct MyStruct {
unsigned p;
unsigned t;
};
class MyClass {
public:
void call() {
ob["o1_10"] ={10, 1};
mbp[ob["o1_10"].p].insert("o1_10");
ob["o2_20_2"] ={20, 2};
mbp[ob["o2_20"].p].insert("o2_20");
ob["o3_30"] ={30, 3};
mbp[ob["o3_30"].p].insert("o3_30");
ob["o4_4_4"] ={4, 4};
mbp[ob["o4_4"].p].insert("o4_4");
ob["o5_10"] ={10, 4};
mbp[ob["o5_10"].p].insert("o5_10");
}
private:
map<unsigned,set<string, compare>> mbp;
// Question: how to define compare using struct, operator(), statice metthod or external method so that
// compare fetches ob[ol] and ob[0l2] and decide based on some rules
// so, comparions is not based on ol and o2 and it is based on some p and t in ob[o1] and ob[02]
// static bool compare2(string& o1, string& o2) {
// // TODO: iS it possible to use this as customed comparison for set in mbp?
// // if (this->ob[ol].p > ob[o2].p) return true;
// // if (ob[ol].p == ob[o2].p && ob[ol].t < ob[o2].t) return true;
// return false;
// }
map<string, MyStruct> ob;
};
int main() {
MyClass my_class;
my_class.call();
return 0;
}