1

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;
}
  • 5
    if you know Java, then you need to understand that there is more to forget than to benefit when transitioning to C++. Read here: https://stackoverflow.com/questions/274626/what-is-object-slicing, though thats only one of the issues you get by trying to apply java to c++... – 463035818_is_not_an_ai Feb 15 '22 at 09:22
  • ^That. This is very idiomatic Java and very anti-C++ code. You might want to check out the standard library (e.g. `std::sort`) for what is considered idiomatic C++ code. – Passer By Feb 15 '22 at 09:26
  • 4
    Anyhow, for this question to be answerable, please post a [mcve] – 463035818_is_not_an_ai Feb 15 '22 at 09:26
  • It is right there in what the compiler gave you. You can not convert a Letter (object) to a Sortable this way. But you can handle a Letter* (pointer) as a Sortable*. – SKCoder Feb 15 '22 at 09:30
  • @463035818_is_not_a_number I've added a minimum reproducible example but since I asked the question and read Caleth's answer I think I have a general idea of what I need to learn about. Letter doesn't have the method you mention, so I'm not sure what you meant. – Mathematical Lie Feb 15 '22 at 10:10
  • @SKCoder I understood that - I was asking if there was a way to pass objects of derived classes to objects of their base class like in java. – Mathematical Lie Feb 15 '22 at 10:12
  • "Letter doesn't have the method you mention" sorry, I confused `Sortable` with `Sorter`. Comment removed. – 463035818_is_not_an_ai Feb 15 '22 at 10:15

1 Answers1

2

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
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Thank you Caleth. As 463035818_is_not_a_number pointed out, I can't just apply java to c++. I've been learning c++ for less than half a day, but I will now be investigating templates more. – Mathematical Lie Feb 15 '22 at 10:07
  • @DesmosArtist in particular, `std::sort` already exists, and only if you don't want to mutate an existing sequence would you need to write something like this `sort` – Caleth Feb 15 '22 at 10:21
  • Oh, I know, I actually used std::sort earlier. I just wanted to code sorting algorithms for fun. – Mathematical Lie Feb 15 '22 at 10:31