【问题标题】:C++ Compare Function Weird Behavior Inside A ClassC ++比较类中的函数奇怪行为
【发布时间】:2018-06-02 16:45:32
【问题描述】:

我是 C++ 的新手。我已尽力使标题更有意义。我正在尝试解决 K-NN 问题(在 2D 中)。我发现这段代码有效(也许你可以跳过它,先看问题):

// Example program
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <math.h>  
#include <vector>
using namespace std;

struct Point { 
    double x;
    double y; 
    Point(double a, double b) {
        x = a;
        y = b;
    }
};

double getDistance(Point a, Point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
typedef bool (*comp)(Point, Point);
Point global_origin = Point(0,0);
bool compare(Point a, Point b)
{
   return (getDistance(a, global_origin)< getDistance(b, global_origin));
}

vector<Point> Solution(vector<Point> &array, Point origin, int k) {
    global_origin = Point(origin.x, origin.y);
    priority_queue<Point, std::vector<Point>, comp> pq(compare);
    vector<Point> ret;
    for (int i = 0; i < array.size(); i++) {
        Point p = array[i];
        pq.push(p);
        if (pq.size() > k)
            pq.pop();
    }
    int index = 0;
    while (!pq.empty()){
        Point p = pq.top();
        ret.push_back(p);
        pq.pop();
    }
    return ret;
}

int main()
{
   Point p1 = Point(4.5, 6.0);
   Point p2 = Point(4.0, 7.0);
   Point p3 = Point(4.0, 4.0);
   Point p4 = Point(2.0, 5.0);
   Point p5 = Point(1.0, 1.0);
   vector<Point> array = {p1, p2, p3, p4, p5};
   int k = 2;
   Point origin = Point(0.0, 0.0);
   vector<Point> ans = Solution(array, origin, k);
   for (int i = 0; i < ans.size(); i++) {
       cout << i << ": " << ans[i].x << "," << ans[i].y << endl;
   }
}

但是,如果我想将解决方案部分放入这样的类中:

// Example program
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <math.h>  
#include <vector>
using namespace std;

struct Point { 
    double x;
    double y; 
    Point(double a, double b) {
        x = a;
        y = b;
    }
};
class MySolution {
public:
  double getDistance(Point a, Point b) {
      return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  }
  typedef bool (*comp)(Point, Point);
  Point global_origin = Point(0,0);
  bool compare(Point a, Point b)
  {
     return (getDistance(a, global_origin)< getDistance(b, global_origin));
  } 

  vector<Point> Solution(vector<Point> &array, Point origin, int k) {
      global_origin = Point(origin.x, origin.y);
      priority_queue<Point, std::vector<Point>, comp> pq(compare);
      vector<Point> ret;
      for (int i = 0; i < array.size(); i++) {
          Point p = array[i];
          pq.push(p);
          if (pq.size() > k)
              pq.pop();
      }
      int index = 0;
      while (!pq.empty()){
          Point p = pq.top();
          ret.push_back(p);
          pq.pop();
      }
      return ret;
  }
};


int main()
{
   Point p1 = Point(4.5, 6.0);
   Point p2 = Point(4.0, 7.0);
   Point p3 = Point(4.0, 4.0);
   Point p4 = Point(2.0, 5.0);
   Point p5 = Point(1.0, 1.0);
   vector<Point> array = {p1, p2, p3, p4, p5};
   int k = 2;
   Point origin = Point(0.0, 0.0);
   vector<Point> ans = MySolution().Solution(array, origin, k);
   for (int i = 0; i < ans.size(); i++) {
       cout << i << ": " << ans[i].x << "," << ans[i].y << endl;
   }
}

我用g++编译,得到

kcloset_copy.cpp:32:58: error: reference to non-static member function must be called
      priority_queue<Point, std::vector<Point>, comp> pq(compare);
                                                         ^~~~~~~
1 error generated.

我尝试了几种不同的方法来编写比较函数。当我将每个方法包装在一个类中时,每个方法在一个类之外工作都会失败。我对原因很感兴趣,如果我想上课该怎么做。

感谢您的回复。我尝试了下面提供的所有代码,但它们都不起作用。一些答案甚至提出了两种解决方案,但它们都不起作用。和重载方法一样,它给出了

"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__functional_base:61:21: error: 
      invalid operands to binary expression ('const Point' and 'const Point')
        {return __x < __y;}
                ~~~ ^ ~~~
"

。如果有人能给我任何实际有效的代码,我将不胜感激。

【问题讨论】:

  • 请将您的解决方案添加为答案,而不是几天后您也可以接受自己的答案,请参阅tour 了解更多信息

标签: c++ c++11 g++ clang++


【解决方案1】:

我的朋友解决了问题。把解决方案放在这里给任何可能遇到同样问题的人,注意 global_origin 在类之外(或者你可以将它声明为静态成员并在类之外再次声明它。你也可以在嵌套结构中构建运算符/class 在 MySolution 类中,并将嵌套结构/类作为 priority_queue 的第三个参数传递):

Point global_origin;    
class MySolution {
public:
  double getDistance(Point a, Point b) {
      return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  }
  bool operator()(Point a, Point b)
  {
     return (getDistance(a, global_origin)< getDistance(b, global_origin));
  } 

  vector<Point> Solution(vector<Point> &array, Point origin, int k) {
      global_origin = Point(origin.x, origin.y);
      priority_queue<Point, std::vector<Point>, MySolution> pq;
      vector<Point> ret;
      for (int i = 0; i < array.size(); i++) {
          Point p = array[i];
          pq.push(p);
          if (pq.size() > k)
              pq.pop();
      }
      int index = 0;
      while (!pq.empty()){
          Point p = pq.top();
          ret.push_back(p);
          pq.pop();
      }
      return ret;
  }
};

【讨论】:

    【解决方案2】:

    请跟我重复几次:非成员函数与非静态成员函数不同。非静态成员函数需要调用一个 object(成为函数内部的 this 指针),非成员函数不需要这样的东西。

    解决您的问题最简单的方法不是创建显式比较函数,而是为Point 类型重载operator&lt; 函数,让队列使用标准比较。

    即:

    bool operator<(Point const& p1, Point const& p2);
    

    然后只是

    std::priority_queue<Point> pq;
    

    【讨论】:

      【解决方案3】:

      如果你为你的类型实现了 operator

      bool operator<(Point const & a, Point const & b)
      {
         return (getDistance(a, global_origin)< getDistance(b, global_origin));
      }
      ...
      std::priority_queue<Point> q;
      

      如果您坚持将其实现为单独的仿函数,则需要在该类型上实现 operator():

      struct MyPointCompare {
       bool operator()(Point const & a, Point const & b)
        {
          return (getDistance(a, global_origin)< getDistance(b, global_origin));
        }
      };
      

      【讨论】:

      • 第二种方法给出“错误:使用嵌套类型'MyPointCompare'中'MySolution'的非静态数据成员'global_origin'”
      【解决方案4】:

      因为第二种情况下的“比较”是一个方法而不是一个函数对象。方法与功能不同。 方法与类实例(对象)相关联,并不独立存在。 对非静态方法的引用只能在类的对象创建后才存在,不能在类内引用。在这种情况下,由于 compare 方法不是静态的,对该方法的引用是无效的。

      例如:你可以尝试将 compare 成员定义为 static bool compare(..)

      【讨论】:

        猜你喜欢
        • 2017-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多