2012-01-15 5 views
2

의가 나는 Rectangle 클래스과 같이 있다고 가정 해 봅시다 :다형성

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

지금 내가 처음 힙 width을 기반으로해야한다는 점을 제외 힙로 Rectangles 두 가지 가능성이 다른 목록을 저장하고자 두 번째는 height입니다. 또한 stl의 make_heap 함수를 사용하여 heapify하는 기능을 사용하고자합니다. 이상적으로는 힙에 .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++에서의 기능을 이해하지 못하는 것 같아요 때문에 : 내가 가지고있는 것은 다음과 같다.

+2

구체적으로 "모두 잘못"이라고 생각하십니까? –

답변

3

comp은 멤버 함수 포인터이기 때문에 this을 전달하지 않으면 호출 할 수 없습니다. 당신은 그것을 this을 결합해야합니다

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

std::bind는 C++ 11에서 <functional> 헤더에 발견하고, TR1을 사용도 가능합니다 <tr1/functional>에서 std::tr1::bind로 할 수있다. TR1 또는 C++ 11을 사용할 수 없으면 Boost library이 있습니다.

데모 : http://ideone.com/5zhmg

+0

건배! 감사! – mshang

1

당신은 멤버 함수를 전달한다. 멤버 함수에는 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_ptrmake_heap 기능이 누락 될 것입니다. 당신은 어떻게 든 그것을 제공해야하고, 가장 쉬운 방법은 C++ 11 람다를 통해 아마 : 아마

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에 있습니다.

+0

자세한 설명을 주셔서 감사합니다. – mshang

2

바인딩 이외에도 다른 솔루션은 단순히 생성자 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 

...아마도 조금 과장 될 것입니다.)

+0

좋은 지적. 나는 그런 생각을하지 않았다. 또한, 나는 당신의 two-in-one 솔루션을 좋아합니다. – mshang