Use heap code for two classes c++ without rewriting

77 Views Asked by At

I'm trying to implement a heap code for two different classes and I don't want to rewrite the heap code, as it already works (tested and working)

So I have this first (original) class, let's call it Job with several attributes. Then I modified it to be abstract and have two classes implement this Job class:

class Job {
protected:
    long long value1;
    long long value2;

    ...

public:
    Job(long long value1, long long value2) : value1(value1), value2(value2) {};
    virtual void setValue(long long value);
    virtual long long getValue();
};

class AvailableJob : public Job{

public:
    AvailableJob (long long value1, long long value2): Job(value1, value2) {};

    void setValue(long long value) {
        if (value == -1)
            return;
        value1 = value;
    }

    long long getValue() {
        return value1;
    }
};

class UsedJob : public Job{

public:
    UsedJob (long long value1, long long value2): Job(value1, value2) {};

    void setValue(long long value) {
        if (value == -1)
            return;
        value2 = value;
    }

    long long getValue() {
        return value2 ;
    }
};

The class has more attributes and methods, but those are not relevant for this question.

The issue is that I create two min-heap trees using my HeapStruct class but I want one min-heap using value1 as the reference value and the other min-heap using value2

So I thought this would work:

class HeapStruct{
    private:
        vector<Job> heap;
        long long size;
        long long maxSize;
...
    public:
    HeapStruct(long long maxSize) : maxSize(maxSize) {
    // initialize heap
    }
    long long getValueAt(long long i) {
        return heap.at(i).getValue();
    }
    
    void siftUp(long long i) {
        // siftUp using job::getValue and job::setValue methods
    }

    void siftDown(){};
    Job getMin(){};
    void insertNode(){};
    removeNode(){};
};

I thought that using the methods Job::getValue and Job::setValue would be enough for this to work, but how do I tell HeapStruct to use either AvailableJob or UsedJob. Right now is complaining about the use of an abstract class.

Also, if this is not the best approach and you know a better one, I'm open to try something different.

1

There are 1 best solutions below

0
Swift - Friday Pie On

The class member vector<Job> heap;can store only Job, not derived classes, If you need a single Job-type container, you can make HeapStruct a template working with any T:

template <class T>
class HeapStruct {
private:
        vector<T> heap;
        //...
public:
     T getMin();   // should  we really returning a copy here?
};

and, maybe, use SFINAE before C++20, or even limit it with named concepts to a Job-derived class with C++20:

template <std::derived_from<Job> T>
class HeapStruct {

If you have to use same type for any job, but not mixing them together, you can add a virtual base class there to perform type erasure:

class HeapStructBase {
public:
   virtual Job& getMin() = 0;

   // just a cast, to get something like getMin<AvailableJob>()
   template<class V>  
   auto getMin() { return dynamic_cast<V&>(this->getMin()); }
};

template <std::derived_from<Job> T>
class HeapStruct : public HeapStructBase {
private:
        vector<T> heap;
public:
     T& getMin() override;   // T derived from Job
};