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