Home > Net >  Pass vector of objects of derived class to function which takes vector of objects of base class
Pass vector of objects of derived class to function which takes vector of objects of base class

Time:02-16

I'm new to c but I have experience with OOP in other languages such as java. I have three classes: class Sortable {...};, class Letter: Sortable {...};, and class Sorter {...};. Sorter has a public function vector<Sortable> sort(vector<Sortable> items_).

In main, I make a vector, vector<Letter> letters; which I give some Letter objects. I then create a Sorter object and use its sort function:

Sorter sorter = Sorter();
vector<Sortable> sortedLetters = sorter.sort(letters);

On that second line I get two errors: No viable conversion from 'vector<Letter>' to 'vector<Sortable>' and No viable conversion from 'vector<Sortable>' to 'vector<Letter>'. That error makes sense but it leaves me with no idea how to make a function which accepts any derived class of a base class.

minimum reproducible example:

#include <iostream>
#include <vector>

using namespace std;

class Sortable {
public:
    virtual int getSortValue() = 0;
};

class Letter: Sortable {
    int sortValue;
public:
    Letter(int f);
    int getSortValue();
};

Letter::Letter(int f) {
    sortValue = f;
}

int Letter::getSortValue(){
    return sortValue;
}

class Sorter {
public:
    Sorter();
    vector<Sortable> sort(vector<Sortable> items_);
};

Sorter::Sorter() = default;

vector<Sortable> sort(vector<Sortable> items_) {
    return items_;
}

int main(int argc, const char * argv[]) {
    Letter a = Letter(1);
    Letter b = Letter(4);
    Letter c = Letter(3);
    Letter d = Letter(2);
    vector<Letter> letters {a,b,c,d};
    Sorter sorter = Sorter();
    vector<Letter> sortedLetters = sorter.sort(letters);
    
    return 0;
}

CodePudding user response:

The idiomatic way that this would be done in C is to discard class Sortable and class Sorter, and have a free function template sort. Letter could either have an operator <, or you would use a function that defined "less than" for a particular context.

Since C 20 things have gotten slightly nicer, as you can define operator <=> which synthesizes each of < > <= >=, and you can = default a comparison to have it compare each base and member.

template <typename T, typename Pred = std::less<T>> // default comparison is <
/* since C  20 */ requires std::strict_weak_order<Pred, T, T>
std::vector<T> sort(std::vector<T> items, Pred less) {
    // items is a copy, so we aren't mutating the source object
    std::sort(items.begin(), items.end(), less); // or whatever
    return items;
}

class Letter {
    friend bool operator<(const Letter &, const Letter &); // pre C  20 this is sufficient to sort, but doesn't define >, <=, >=
    friend auto operator <=>(const Letter &, const Letter &) = default; // post C  20, defines < > <= >= too
}

bool someSpecificLetterOrder(const Letter &, const Letter &); // for sorting by a different criteria
  •  Tags:  
  • c
  • Related