2

I've recently begun learning c++ (no prior programming knowledge). I've used the book "Jumping into c++" By Alex Allain and i've found it most useful! However i've reached the chapters of classes, inheritence and polymorphism, and while i do understand most of it I just cannot wrap my head around this one problem.

In the book I am asked to solve the following problem:

Implement a sort function that takes a vector of pointers to an interface class, Comparable, that defines a method, compare(Comparable& other), and returns 0 if the objects are the same, 1 if the object is greater than other, and -1 if the object is less than other. Create a class that implements this interface, create several instances, and sort them. If you're looking for some inspiration for what to create—try a HighScoreElement class that has a name and a score, and sorts so that the top scores are first, but if two scores are the same, they are sorted next by name.

I've created the classes Comparable and HighScores:

class Comparable {

public:

    virtual int compare(Comparable& other)=0;

};



class HighScore : public Comparable {

public:
    HighScore(int, std::string);

    virtual int compare(Comparable& other);


private:
    int highscore;
    std::string name;

};

If i try to overwrite the inherited function in HighScore, i am not able to compare, for instance the int highscore, with the int highscore of (Comparable& other), since i cannot access the other.highscore. Example below:

int HighScore::compare(Comparable& other){

    if (highscore == other.highscore) {
        return 0;
    }

    //...
}

I thought i could maybe change the virtual method to something like:

int HighScore::compare(HighScore& other){

    if (highscore == other.highscore) {
        return 0;
    }

    //...
}

Since that would allow me to access other.highscore (and i had hoped that i would work since HighScore also can be considered a Comparable. But alas no such luck. What should I do, i litterally have no clue on how to continue and i would appreciate any help i can get. Thanks :)

3 Answers3

1

Indeed, trying to choose behaviour based on the run-time type of two or more objects is a bit fiddly in a single-dispatch language like C++.

The simplest solution is to use RTTI to determine whether the other object has a type comparable with ours:

int HighScore::compare(Comparable& other){

    int other_highscore = dynamic_cast<HighScore&>(other).highscore;

    if (highscore == other_highscore) {
        return 0;
    }

    //...
}

This will throw an exception if the types aren't comparable, which is probably the best you can do.

Alternatively, you could implement a double-dispatch mechanism (such as the "Visitor Pattern"), involving two virtual functions. I'll let you research it yourself, since an example would be long-winded and not particularly inspiring.

Hopefully, you will soon learn how to do this using compile-time generics rather than run-time abstract interfaces, which is much more idiomatic in C++. If the book doesn't teach you that, throw it away and get one of these instead.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • In case of failed dynamic_cast on reference there will be exeption thrown. `9 The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws an exception (15.1) of a type that would match a handler (15.3) of type std::bad_cast (18.7.2).` – alexrider Apr 23 '13 at 18:50
  • @alexrider: Exactly, that's what I said immediately after the example. How else would you handle an attempt to compare two types that can't be compared? – Mike Seymour Apr 23 '13 at 18:51
  • Thank you very much, I dont understand half of what you're saying so it might be a good idea to find other books on the subject :) Thank you very much for your help and time! – Rolf Jensen Apr 23 '13 at 18:53
0

You can write a pulic getter function to get the score

class Comparable {
public:
    int get_score() const = 0;
    //
}

class HighScore : public Comparable {
public:
    int get_score() const { return highscore; }

and then use that for comparison.

int HighScore::compare(Comparable& other){

    if (highscore == other.get_score()) {
                           ^^^^^^^^^^^
        return 0;
    }

    //...
}

But since only the derived class has highscore member you should probably change what you pass to compare.

int HighScore::compare(HighScore& other)

OR move highscore member to the base class. Whichever males sense to you.

stardust
  • 5,918
  • 1
  • 18
  • 20
  • Do you mean add a `get_score()` function to the `Comparable` class (since that's all the static type information we have for `other`)? What about the other derived classes that want to compare height, weight or number of elephants? Should `Comparable` contain getters for all those things? – Mike Seymour Apr 23 '13 at 18:37
  • @MikeSeymour oh ya. Right. – stardust Apr 23 '13 at 18:39
  • @MikeSeymour I added it there because highscore is not actually a member of the base. So I overlooked that he passed comparable. However I think he should pass **HighScore** class instead of comparable. – stardust Apr 23 '13 at 18:43
  • But the abstract interface requires that you pass `Comparable`, so that's not an option. – Mike Seymour Apr 23 '13 at 18:47
0

I'd suggest picking another book on the subject. Since this exercise seemed to be vague and doesn't give good understanding on polymorphism. The tricky part is that when you get Comparable in your compare method you have no clue, if it is HighScore or some other derived class. And in case if the class you are attempting to compare is not an instance of HighScore such terms as equal less and greater doesn't have any meaning. Thus there is no way to solve this correctly. You can of course use dynamic_cast to check if it is HighScore, but still if it doesn't there is no good answer if it greater, lesser or equal to something that isn't a HighScore.
Just imagine that there is something like class Color : public Comparable { exists. What should you return in case if you get Color to be compared with HighScore? Is blue bigger than 10, or Yellow less than 15, what red is equal to?

alexrider
  • 4,449
  • 1
  • 17
  • 27