2009-10-22 145 views
4

我想在特定的类中按某种顺序对某个结构体的向量进行排序。我已经写了一个类的结构和谓词函数的定义,并在这个结构和函数的类的方法中运行std :: sort。但编译错误已经发生。 gcc版本是4.0.1,操作系统是Mac OSX。代码如下:C++ std :: sort类中的谓词函数

class sample { 
public: 
    struct s { 
    int x; 
    int y; 
    }; 

    bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
    } 

    int func(void) { 
    std::vector <struct s> vec; 

    // ... 

    sort(vec.begin(), vec.end(), cmp); // compilation error 

    // ... 

    return 0; 
    } 
}; 

int main(void) { 
    sample *smp = new sample(); 
    smp->func(); 
    return 0; 
} 

错误消息是巨大而复杂的。所以这是它的前两行。

sortSample.cpp: In member function 'int sample::func()':
sortSample.cpp:51: error: argument of type 'bool (sample::)(sample::s, sample::s)' does not match 'bool (sample::*)(sample::s, sample::s)'
...

代替上述方法,代码可以通过以下方式正确运行。

  1. 定义struct s和功能cmp()class sample
  2. 删除 函数cmp()并定义运算符 <的重载struct s

每种方法的示例代码如下。

1)

struct s { 
    int x; 
    int y; 
}; 

bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
    return a.y < b.y; 
    else 
    return a.x < b.x; 
} 

class sample { 
// ... 

2)

struct s { 
    int x; 
    int y; 

    bool operator<(const struct s & a) const { 
    if (x == a.x) 
     return y < a.y; 
    else 
     return x < a.x; 
    } 
}; 

谁能告诉此行为的机制?为什么第一种方法调用编译错误?

谢谢。

回答

12

在第一种情况下,cmp被声明为class sample的成员函数,因此需要使用this指针来调用它。由于this指针不可用,编译器正在抱怨它。通过声明cmpstatic函数,可以使其工作,因为静态函数不需要此指针来调用。在第二种情况下,由于cmp再次被声明为独立函数,它的行为与静态函数相同。在第三种情况下(带有重载运算符),排序算法将负责为向量中的每个对象调用函数,并因此进行编译。

6

由于cmp与示例的任何特定实例无关,因此使其成为静态成员函数。

5

它可以在你准备使用操作符()被列为第三种方法:

bool operator() (const s& a, const s& b) const 
{ 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
} 

sort(vec.begin(), vec.end(), *this); 
+0

哇,这是一个可怕的把戏。谢谢!这是我可以让比较运算符访问类实例的成员以及要比较的两个对象的唯一方法 - 这真的有所帮助,因为在我的情况下,它允许比较对象使用相对的32位索引到一个64位指针。 – Deadcode 2010-02-13 12:55:28

+0

请注意,调用sort()的方法会将* this的副本传递给它,而不是引用或指针,因此如果使用此技巧,请确保副本仅包含谓词所需的成员 - 最好只有一个32位或64位成员(必要时使用“this”的继承和投射)。 – Deadcode 2010-02-13 14:29:38

+0

另请注意,* this的副本不仅被传递给sort(),而且还会继续递归传递给实用函数sort()使用,具体取决于正在使用的STL实现。 – Deadcode 2010-02-13 14:36:47

0

我认为类之外定义cmp是最好的,因为你只能做一个功能的成员函数,当您需要它可以访问课堂中的一些私人功能,从逻辑上来说,它感觉就在那里。 cmp只是一个实用函数,它为您的类sample提供了实现的功能,但实际上并不需要访问私有成员。此外,它可能不会在对象的上下文中被调用(它的唯一操作在其参数上工作; this指针上没有任何操作),也不必在类sample::cmp的上下文中调用它。虽然看起来像一个微不足道的小问题,但通常不必要的访问权限可能是许多软件错误或设计卷积来源的开始。

完成上述操作的附加好处是您的std::sort的调用将起作用,这将回答您的问题。