使用类成员函数作为函数指针?

时间:2017-09-19 05:04:26

标签: c++

我试图将一个类的成员函数的函数指针传递给std :: unique(),并且我得到一些编译错误,这些错误是我无法解密的。

// So this will otherwise compile
class Vec2 {};
class Polygon {};

// ConvexHull.h:
#include <vector>
#include <algorithm>
class ConvexHull {
public:
   // Used to sort an array of vectors so the bottom-right element is first:
   bool bottomRight(const Vec2& a, const Vec2& b);
   // Used to determine if coordinates are equivalent:
   bool vecEqual(const Vec2& a, const Vec2& b);
   Polygon chGrahamScan(std::vector<Vec2> points);
};

// ConvexHull.cpp:
bool ConvexHull::bottomRight(const Vec2& a, const Vec2& b) {
  // implementation...
  return false; // So this will otherwise compile
}

bool ConvexHull::vecEqual(const Vec2& a, const Vec2& b) {
  // implementation...
  return false; // So this will otherwise compile
}

Polygon ConvexHull::chGrahamScan(std::vector<Vec2> points) {
  // Sort according to bottom right:
  std::sort(points.begin(),points.end(),bottomRight); // !!!Does not compile!!!
  std::vector<Vec2>::iterator it;
  // Get rid of duplicate points:
  it = std::unique(points.begin(),points.end(),vecEqual); // !!!Does not compile!!!
  // rest of implementation...
  Polygon poly; // So this will otherwise compile
  return poly;
}

int main(){return 0;} // again, to allow this to otherwise compile

忽略两条断线,这足以编译一些东西。请帮忙!我不确定我在这里做错了什么。我知道这个测试代码说成员函数是公共的,但我的最终目标是让它们成为隐藏在用户之外的私有函数,但仍然在ConvexHull :: chGrahamScan()内部使用sort和unique。这些不是我打算使用的唯一两种比较方法。其他需要引用由ConvexHull类的实例维护的内部状态数据。我的初始解决方案(显然完全有效)的方法不属于任何类。相反,所有的状态数据和比较函数都在一个全局的匿名命名空间中,但这破坏了我的项目的线程安全性,所以我决定走这条路。

如果您将其复制并粘贴到空项目中,您应该会看到我遇到的错误。它说我需要使用。*或 - &gt; *作为成员函数指针。但是,尝试这样做会给我带来其他错误,说这些函数不能用作成员函数,因为它们属于&#34;未解析的重载函数&#34;。

如果事实证明我不能做这样的事情,我怎样才能最好地实现std :: sort和std :: unique,以便传递给它们的比较函数使用定义外部的状态数据函数本身在不违反线程安全的情况下使用全局变量?我之前的解决方案做了类似的事情:

namespace {
  Vec2 point0; // state data that other comparison functions like
               // bottomRight and vecEqual need
  bool bottomRight(/*...*/){/*...*/}
  bool vecEqual(/*...*/){/*...*/}
}

// Accesses global data. Bad!
Polygon chGrahamScan(std::vector<Vec2> points) {
  std::sort(points.begin(),points.end(),bottomRight);
  std::vector<Vec2>::iterator it;
  it = std::unique(points.begin(),points.end(),vecEqual);
  // etc..
}

2 个答案:

答案 0 :(得分:2)

如果要将sort函数与比较器一起使用,请将比较器写为单独的对象,而不是将代码放在ConvexHull类中。除非您在ConvexHull中需要一些私有数据,否则您的比较器不需要成为该类的一部分。

class ConvexHull
{
    // ... rest of class as shown above ...
    private:
       // declare friend so comparator can use private data.
        friend struct VectorComparator;
};

struct VectorComparator
{
    explicit VectorComparator( ConvexHull * hull ) : hull_( hull ) {}
    bool operator()( const Vec2& a, const Vec2& b ) const
    {
        // ... compare the two Vec2 objects here using private data from ConvexHull ...
    }
    ConvexHull * hull_;
};

然后您可以使用VectorComparator作为std :: sort。

的参数
ConvexHull * hull = new ConvexHull;
std::sort(points.begin(),points.end(), VectorComparator(hull) );

您可以为唯一功能创建单独的比较器。

struct UniqueVectorComparator
{
    bool operator()( const Vec2& a, const Vec2& b ) const
    {
        // .. compare the two Vec2 objects here.
    }
};

it = std::unique(points.begin(),points.end(), UniqueVectorComparator() );

答案 1 :(得分:1)

正如编译器所说,使您的函数保持静态并使用作用域运算符:

class ConvexHull {
public:
   // Used to sort an array of vectors so the bottom-right element is first:
   static bool bottomRight(const Vec2& a, const Vec2& b);
   // Used to determine if coordinates are equivalent:
   static bool vecEqual(const Vec2& a, const Vec2& b);
   Polygon chGrahamScan(std::vector<Vec2> points);
};
...
std::sort(points.begin(),points.end(),ConvexHull::bottomRight); // !!!Does not compile!!!