C++ 中堆类的多态性;

发布于 2024-12-27 04:05:53 字数 863 浏览 5 评论 0原文

假设我有一个像这样的 Rectangle 类:

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

现在我希望将两个可能不同的 Rectangles 列表存储为堆,但第一个堆应该基于 宽度,第二个高度。另外,我希望使用stl的make_heap函数来堆化。理想情况下,我应该能够在堆上调用 .heapify() ,并且根据它所属的类,相关堆应该通过将正确的比较函数传递给 来堆化自身make_heap,也许使用动态调度。我所拥有的是以下内容:

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
}

这都是错误的,因为我想我只是不理解 C++ 中的函数,这就是为什么我需要你的帮助。

Let's say I have a Rectangle class like so:

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. Also, I wish to use the stl's make_heap function to heapify. 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. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱要勇敢去追 2025-01-03 04:05:53

因为comp是一个成员函数指针,所以如果不传递this就不能调用它。您需要将 this 绑定到它:

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

std::bind 可以在 C++11 的 标头中找到,并且也可以使用 TR1 在 中作为 std::tr1::bind 使用。如果您无法使用 TR1 或 C++11,可以使用 Boost 库

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

Because comp is a member function pointer, it cannot be called without passing this. You need to bind this to it:

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. If you can't use TR1 or C++11, there's a Boost library for it.

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

々眼睛长脚气 2025-01-03 04:05:53

除了绑定之外,另一种解决方案是简单地要求将函数指针传递给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;

然后:

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

有趣的是,您甚至可以更进一步,只需一点想象力,实际上可以同时保留两个订单。

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

虽然……这可能有点过分了;)

Apart from binding, another solution is simply to ask for a pointer to function to be passed to the constructor of 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 ;)

情独悲 2025-01-03 04:05:53

您正在传递一个成员函数。成员函数有一个 this 指针。 make_heap 函数应该从哪里获取它?

具体来说,使用以下语法调用指向成员函数的指针(对于发明的类 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

obj_ptr 就是 make_heap 函数丢失的。您需要以某种方式提供它,最简单的方法可能是通过 C++11 中的 lambda:

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

或者甚至可能是 std::bind

#include <functional>

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

如果您无权访问这些 C++11功能,请使用 Boost.Bind

You are passing a member function. Member functions have a this pointer. Where should the make_heap function get that from?

Specifically, pointer to member functions are invoked with the following syntax (for an invented class 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. You somehow need to provide it, and the easiest way is probably through a lambda in C++11:

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

Or maybe even 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文