C ++比较一个类中的函数怪异行为

问题描述 投票:0回答:4

我是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;}
                ~~~ ^ ~~~
"

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

c++ c++11 g++ clang++
4个回答
0
投票

问题由我的朋友解决了。只需将解决方案放在可能遇到相同问题的任何人身上,请注意global_origin在类之外(或者您可以将其声明为静态成员并在类外部再次声明它。您还可以在嵌套结构中构建运算符/ 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;
  }
};

-1
投票

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

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

那是:

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

然后就是

std::priority_queue<Point> pq;

-1
投票

如果为您的类型实现operator <,则可以依赖std :: less,prioity_queue的默认模板参数将起作用:

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

-1
投票

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

例如:U可以尝试将比较成员定义为静态bool比较(..)

© www.soinside.com 2019 - 2024. All rights reserved.