Thread: Solution to practice problem 1 from the book Jumping into C++

  1. #1
    Registered User
    Join Date
    Apr 2017
    Posts
    11

    Solution to practice problem 1 from the book Jumping into C++

    Hello,

    I wrote a solution to the following practice 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.

    My code is below
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    class Comparable
    {
        public:
            virtual int compare(Comparable& other)=0;
    };
    
    class HighScoreElement : public Comparable
    {
        public:
            virtual int compare(HighScoreElement& other);
            void set_members(string user_name, int user_high_score)
            {
                name=user_name;
                high_score = user_high_score;
            }
            void print_members()
            {
                cout<<"Name:\t"<<name<<"\tHigh Score:\t"<<high_score<<endl;
            }
            string get_name()
                {
                    return name;
                }
            int get_high_score()
            {
                return high_score;
            }
        private:
            string name;
            int high_score;
    };
    int HighScoreElement :: compare(HighScoreElement& other)
    {
        if(this->high_score>other.high_score) return (1);
        if(this->high_score < other.high_score) return(-1);
        if(this->name>other.name) return(1);
        if(this->name<other.name) return(-1);else return(0);
    }
    
    void sort(vector<Comparable*> comparables)
    {
        cout<<"\nEntering the Sort Function";
        cout<<"\nThis is the state of the vector at the beginning of the sort function  using comparables parameter\n";
        for(int i=0;i<comparables.size();i++)
        {
            ((HighScoreElement*)comparables[i])->print_members();
        }
         Comparable *p_temp_Comparable;
         for(int i=0;i<comparables.size()-i;i++)
        {
            for(int j=i+1; j<comparables.size();j++)
            {
                if(comparables[i]->compare(*comparables[j])<0)
                {
                       p_temp_Comparable = comparables[i];
                       comparables[i]=comparables[j];
                       comparables[j] = p_temp_Comparable;
                }
            }
        }
    }
    int main()
    {
        cout << "Hello world!" << endl;
        HighScoreElement *p_HighScoreElement;
        vector<Comparable*> comparables;
        vector<HighScoreElement*> highscoreelements;
        for(int i =0;i<10;i++)
        {
            p_HighScoreElement = new HighScoreElement;
            p_HighScoreElement->set_members("Ateeque Mohammad", rand()%100);
            comparables.push_back(p_HighScoreElement);
            highscoreelements.push_back(p_HighScoreElement);
        }
        for(int i=0;i<10;i++)
        {
            p_HighScoreElement = new HighScoreElement();
            p_HighScoreElement->set_members("Abdullah Mohammad", highscoreelements[i]->get_high_score());
            comparables.push_back(p_HighScoreElement);
            highscoreelements.push_back(p_HighScoreElement);
        }
    
        for(int i=0;i<10;i+=3)
        {
            p_HighScoreElement = new HighScoreElement();
            p_HighScoreElement->set_members("Abdurrahman Mohammad", rand()%100);
            comparables.push_back(p_HighScoreElement);
            highscoreelements.push_back(p_HighScoreElement);
        }
        cout<<"\nThis is the state of the vector after the auto fill was run\n";
        /*for ( vector<HighScoreElement*>::iterator itr = highscoreelements.begin(), end = highscoreelements.end();
        itr != end; ++itr )
            (*itr)->print_members();
        */
    
        for(int i=0;i<highscoreelements.size();i++)
        {
            highscoreelements[i]->print_members();
        }
        cout<<"\nThis is the state of the vector after the auto fill was run using comparables\n";
        for(int i=0;i<comparables.size();i++)
        {
            ((HighScoreElement*)comparables[i])->print_members();
        }
        sort(comparables);
    
        cout<<"\nThis is the state of the vector after the sorting of the vector\n";
        for(int i=0;i<highscoreelements.size();i++)
        {
            highscoreelements[i]->print_members();
        }
        //auto_fill_vector();
        return 0;
    }
    When I build the code I get the below errors.

    \Sort_Inheritance\main.cpp|87|error: invalid new-expression of abstract class type 'HighScoreElement'|
    C:\Users\atmoha\OneDrive\CPLUSPLUS\Chapter 27\Sort_Inheritance\main.cpp|16|note: because the following virtual functions are pure within 'HighScoreElement':|
    C:\Users\atmoha\OneDrive\CPLUSPLUS\Chapter 27\Sort_Inheritance\main.cpp|11|note: virtual int Comparable::compare(Comparable&)|
    C:\Users\atmoha\OneDrive\CPLUSPLUS\Chapter 27\Sort_Inheritance\main.cpp|96|error: invalid new-expression of abstract class type 'HighScoreElement'|
    C:\Users\atmoha\OneDrive\CPLUSPLUS\Chapter 27\Sort_Inheritance\main.cpp|105|error: invalid new-expression of abstract class type 'HighScoreElement'|

    Looks like the Compare method in the class HighScoreElement is not overriding the Compare method of the Comparable class when I did declare it pure virtual in Comparable class and then made the declaration of the method as a virtual in HighScoreElement class and then defined it as well.

    Can someone point out what am I doing wrong?

  2. #2
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    Since the tags took out the empty lines the error in line 87 appears on line 75 in the post here

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by amohad
    Looks like the Compare method in the class HighScoreElement is not overriding the Compare method of the Comparable class when I did declare it pure virtual in Comparable class and then made the declaration of the method as a virtual in HighScoreElement class and then defined it as well.

    Can someone point out what am I doing wrong?
    The problem is that an override of a virtual function must retain the function signature, i.e., the name of the function and its parameter list. It must also retain the function return type, though an exception is made for covariant returns types. In your case, the issue is that your derived class' function changes the type of the parameter, therefore it is not an override but rather becomes an overload.

    What you should do, therefore, is declare compare member function in HighScoreElement to be exactly the same as in Comparable, except that this time you actually define it instead of declaring it pure virtual. You would thus have to use dynamic_cast to convert the parameter to HighScoreElement or a pointer thereof.

    A few other points to note:
    • This is actually not the conventional way to sort objects of different types with special comparison considerations. What we would normally do is to either overload operator< for the class type, or provide a comparison function (or function object, possibly as a lambda) that returns true if the first argument is "less than" the second argument, and false otherwise, for whatever notion of "less than" you want, and then use std::sort or some other sorting algorithms designed with this approach in mind. Hence, this exercise is purely for you to practise the use of inheritance and polymorphism, and should not be the strategy to adopt when sorting in the future.
    • You correctly declared the compare member function according to the instructions, but note that it is not const-correct. Comparing a Comparable shouldn't involve changing its observable state, hence the compare member function should have been declared:
      Code:
      virtual int compare(const Comparable& other) const = 0;
    • Your sort function should not mention HighScoreElement at all. This is the point of the polymorphism, i.e., you can use your sort function with any class type that implements the Comparable interface. If your sort function mentions HighScoreElement, then it is tightly coupled to HighScoreElement such that you might as well ditch the whole Comparable interface business and just implement sort for a std::vector<HighScoreElement> instead.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    Thanks very much for your response. Your comments are really helpful and the I now understand the concept of the override of a virtual function and retaining the function signature.

    About the const-correct below
    Code:

  5. #5
    Registered User
    Join Date
    Apr 2017
    Posts
    11
    About the const-correct below

    Code:
    virtual int compare(const Comparable& other) const = 0;


    What is the second const for before the =0?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by amohad
    What is the second const for before the =0?
    It indicates that the function can be called when the object is const, or from a context in which the object is treated as if it were const (e.g., when it is passed by const reference).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 10-10-2018, 02:12 PM
  2. Jumping into C++ - Chapter 7 - Practice problem 1
    By ambro1987 in forum C++ Programming
    Replies: 2
    Last Post: 09-18-2017, 09:00 AM
  3. Jumping into C++ : Chapter 6 Practice Problem 2
    By Markkusz in forum C++ Programming
    Replies: 3
    Last Post: 10-09-2015, 08:26 AM
  4. Jumping into c++ practice problem poker chapter 9
    By menkle in forum C++ Programming
    Replies: 2
    Last Post: 09-06-2015, 02:43 PM
  5. Jumping Into C++ Chapter 14 Practice Problem 1
    By ArtemisFowl2nd in forum C++ Programming
    Replies: 5
    Last Post: 04-16-2014, 09:36 PM

Tags for this Thread