简体   繁体   English

C ++中堆类的多态性

[英]Polymorphism for heap classes in C++

Let's say I have a Rectangle class like so: 假设我有一个像这样的Rectangle类:

class Rectangle {
public:
    double width;
    double height;
}

Now I wish to store two possibly different lists of Rectangles as heaps, except that the first heap should be based on width and the second on height . 现在,我希望将两个可能不同的Rectangles列表存储为堆,除了第一个堆应基于width ,第二个堆应基于height Also, I wish to use the stl's make_heap function to heapify. 另外,我希望使用stl的make_heap函数进行堆化。 Ideally, I should be able to call .heapify() on a heap, and based on the class that it belongs to, the heap in question should heapify itself by passing the correct comparison function to make_heap , perhaps using dynamic dispatch. 理想情况下,我应该能够在堆上调用.heapify() ,并且基于它所属的类,所讨论的堆应该通过将正确的比较函数传递给make_heap ,也许可以使用动态分配。 What I have is the following: 我有以下内容:

class Heap {
public:
    vector<Rectangle> data;
    virtual bool comp(Rectangle a, Rectangle b);
    void heapify() { make_heap(data.begin(), data.end(), comp); }
    // other methods that make use of comp directly
}

class WidthHeap : public Heap {
    bool comp(Rectangle a, Rectangle b); // compares by width
}

class HeightHeap : public Heap {
    bool comp(Rectangle a, Rectangle b); // compares by height
}

This is all wrong because I guess I just don't understand functions in C++, which is why I would like your help. 这都是错误的,因为我想我只是不了解C ++中的函数,这就是为什么我需要您的帮助。

Because comp is a member function pointer, it cannot be called without passing this . 因为comp是成员函数指针,所以不传递this不能调用this You need to bind this to it: 您需要this绑定到它:

std::make_heap(data.begin(), data.end(), std::bind(&Heap::comp, this, _1, _2));

std::bind can be found in the <functional> header in C++11, and also available as std::tr1::bind in <tr1/functional> using TR1. std::bind可以在C ++ 11的<functional>标头中找到,也可以使用TR1在<tr1/functional> std::tr1::bind中使用。 If you can't use TR1 or C++11, there's a Boost library for it. 如果您不能使用TR1或C ++ 11,则可以使用Boost库

Demo: http://ideone.com/5zhmg 演示: http : //ideone.com/5zhmg

Apart from binding, another solution is simply to ask for a pointer to function to be passed to the constructor of Heap . 除了绑定之外,另一种解决方案是简单地要求将指向函数的指针传递给Heap的构造函数。

// C++03
typedef bool (*CompType)(Rectangle const&, Rectangle const&);

// C++11 (to allow for lambdas and predicates)
typedef std::function<bool(Rectangle const&, Rectangle const&)> CompType;

And then: 接着:

class Heap {
public:
  explicit Heap(CompType cmp): cmp(cmp) {}

  void heapify() {
    std::make_heap(data.begin(), data.end(), cmp);
  }

private:
  CompType cmp;
  std::vector<Rectangle> data;
}; // class Heap

What is interesting, is that you can even go further, and actually keep both orders at once with a little imagination. 有趣的是,您甚至可以走得更远,并在一点点想象力的情况下同时保持两个订单。

class Heap {
public:
  Heap():
    byLength([](Rectangle const& l, Rectangle const& r) {
      return l.length < r.length; }),
    byWidth[](Rectangle const& l, Rectangle const& r) {
      return l.width < r.width; }),
  {}

  void heapify() {
    std::make_heap(data.begin(), data.end(), byLength);
    std::make_heap(ref.begin(), ref.end(),
      [](Rectangle const* l, Rectangle const* r) {
        return byWidth(*l, *r);
      });
  }

private:
  CompType byLength;
  CompType byWidth;
  std::vector<Rectangle> data;
  std::vector<Rectangle*> ref;
}; // class Heap

Although... it's probably a little overkill ;) 虽然...可能有点矫kill过正;)

You are passing a member function. 您正在传递成员函数。 Member functions have a this pointer. 成员函数具有this指针。 Where should the make_heap function get that from? make_heap函数应从make_heap获取?

Specifically, pointer to member functions are invoked with the following syntax (for an invented class X ): 具体来说,使用以下语法(对于本发明的类X )调用成员函数的指针:

X* obj_ptr; // initialize somewhere
typedef void (X::*mem_ptr)();
mem_ptr mem_fun = &X::some_invented_function;
(obj_ptr->*mem_fun)(); // extra parens needed

The obj_ptr is what the make_heap function would be missing. obj_ptr是缺少make_heap函数的内容。 You somehow need to provide it, and the easiest way is probably through a lambda in C++11: 您以某种方式需要提供它,最简单的方法可能是通过C ++ 11中的lambda:

std::make_heap(data.begin(), data.end(),
    [this](Rectangle r1, Rectangle r2){
      return comp(r1,r2);
    });

Or maybe even std::bind : 或者甚至std::bind

#include <functional>

using std::placeholders;
std::make_heap(data.begin(), data.end(), std::bind(&X::comp, this, _1, _2));

If you don't have access to these C++11 functionalities, please resort to Boost.Bind . 如果您无权使用这些C ++ 11功能,请使用Boost.Bind

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM