【问题标题】:C++ std::sort with predicate function in ClassC++ std::sort 与类中的谓词函数
【发布时间】:2009-10-22 06:42:03
【问题描述】:

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

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:在成员函数'int sample::func()'中:
sortSample.cpp:51: 错误: 'bool (sample::)(sample::s, sample::s)' 类型的参数不匹配'bool (sample::*)(sample::s, sample:: s)'
...

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

  1. 定义struct s 和函数cmp()class sample 之外。
  2. 删除 函数cmp() 并定义运算符 &lt; 中的 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;
  }
};

谁能说出这种行为的机制?为什么第一种方法会调用编译错误?

谢谢。

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        可以在您的可能性中列出的第三种方法是使用 operator():

        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);
        

        【讨论】:

        • 哇,这是一个很棒的技巧。谢谢!这是我可以让比较运算符访问类实例的成员以及要比较的两个对象的唯一方法——这确实很有帮助,因为在我的情况下,它允许比较对象使用相对的 32 位索引到一个 64 位指针。
        • 请注意,这个调用 sort() 的方法将 *this 的副本传递给它,而不是引用或指针,因此如果您使用此技巧,请确保该副本仅包含谓词需要——最好只有一个 32 位或 64 位成员(必要时使用“this”的继承和强制转换)。
        • 另请注意,*this 的副本不仅会传递给 sort(),还会递归地传递给 sort() 使用的实用函数,具体取决于所使用的 STL 实现。
        【解决方案4】:

        我认为在类之外定义cmp 是最好的,因为您应该只在需要访问类中的某些私有功能时才将函数设为成员函数,并且从逻辑上讲,它在那里是正确的。 cmp 只是一个实用函数,它为您的类 sample 提供实现功能,但它实际上并不需要访问私有成员。此外,它可能不会在对象的上下文中被调用(它的唯一操作对其参数起作用;this 指针上没有任何内容),也不能在类sample::cmp 的上下文中调用它。虽然这似乎是微不足道的一点,但一般来说,给函数或代码提供不必要的访问广度可能是许多软件错误或设计卷积的根源。

        执行上述操作的额外好处是您可以调用std::sort,从而回答您的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-22
          • 2011-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-21
          相关资源
          最近更新 更多