简体   繁体   中英

Priority Queue implemented by Vector using Abstract Class C++

I am trying to implement a Priority Queue using a Vector template in C++. I am most comfortable with Java and want to mimic the idea of an Interface, where all objects that can use the Priority Queue are required to implement certain methods.

I know that C++ does not support Interfaces, however, someone suggested that by tapping into Multiple Inheritance this could be achieved by creating an Abstract Class and requiring some virtual functions.

I would like all objects that can use the Priority Queue to implement:

public:
int compareTo(Comparable &obj);

Here is a C++ Abstract Class that achieves this: Comparable.h

class Comparable {
public:
    Comparable();
    ~Comparable();
    virtual int compareTo(Comparable &obj) = 0;
};

This works great, no errors are formed from supplying the Abstract Class to the Vector template:

vector<Comparable> *mElements = new vector<Comparable>(); // no error

It is not until I try to use polymorphism in a class that inherits from the Comparable class that I run into an issue. Because the Method signature receives a Comparable&, I am having trouble accessing the members of the class that extends Comparable:

int Event::compareTo(Comparable& obj) {
    // Min-Heap - time of currentObject is less than e.mTime
    Event e = (Event) obj; // Doesn't work - No C-style cast (can I make one and how?)
// if I trying obj.mTime, this won't work because it is not a member of the Comparable class


if (mTime < e.mTime) return Delta::NEGATIVE_CHANGE;
if (mTime > e.mTime) return Delta::POSITIVE_CHANGE;
    return return Delta::NO_CHANGE;
}

All I need to do is compare the time in this example, but I would like to design the class so that clients only have to inherit from the Comparable class and implement the one method for use of the priority queue.

Thanks for any help in advanced!

You are searching for dinamic_cast http://en.cppreference.com/w/cpp/language/dynamic_cast

dinamic_cast has a ugly name cause you shouldn't use it too much. In this case, you don't need it.

First, in C++ you can overload operators (<, >, ==...). If these operators doesn't exist, the class can't be compared. It's more natural and easy for compare :)

Second, you can use a generic template:

template<class T>
class Comparable {
public:
    Comparable();
    ~Comparable();
    virtual int compareTo(T &obj) = 0;
};

class event : public Comparable<event> {
    //...
    public:
        int compareTo(event &e) override;
};

You can detect wrong types in compile time, you don't need cast in execution time :)

override is one c++11 flag for compiler: "This function should override one parent function, check it". You can remove it freely if you don't use C++11

Actually, you don't need the Comparable class at all, if the PriorityQueue class is a template itself. It will compile for types that implement compareTo and won't compile for types that don't implement it.

template <class T>
class PriorityQueue {
    ...
    void someMethod(const T& obj) {
        if (someOtherObj.compareTo(obj)) {
            ...
        }
    }
    ...
}

As I previously said in a comment, the STL ordered containers use functors instead of requiring some specific interface for their elements. Easier than using a functor is using < to compare objects:

if (someOtherObj < obj) {

That Comparable class actually fits the ideia of a concept (C++14), not an abstract interface. It helps to clarify for a template class/function what is its required interface, but concepts are a very new feature of the C++ language and not widely supported or even known.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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