0

I have a base class Participant and I need to sort object in array of participant by quantity of their prizes or diplomas. The virtual function get_data return this number. But whileI try to sort, i've got error Access violation executing in row with comparing 2 numbers. if (p[j].Get_Data() < p[i].Get_Data()) { This is my full code:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Participant {
protected:
    string name;
    string surname;
    vector <string> type;
    int age;
public:
    Participant() : name(""), surname(""), type(), age(0)
    {}
    Participant(string name, string surname, vector <string> type, int age) {
        this->name = name;
        this->surname = surname;
        this->type = type;
        this->age = age;
    };
    Participant(const Participant& other) : name(other.name), surname(other.surname), type(other.type), age(other.age)
    {
    }
    Participant& operator=(const Participant& other)
    {
        name = other.name;
        surname = other.surname;
        type = other.type;
        age = other.age;
        return *this;
    }
    virtual int Get_Data() {
        return 0;
    }
    friend void Sort(Participant* p);
};

class Diploma : public Participant {
protected:
    vector<int> places;
    vector <string> type_d;
public:
    Diploma() : places(), type_d{}
    {}
    Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d);
    int Get_Data() override {
        cout << "diplom prize" << endl;
        cout << type_d.size() << endl;
        return type_d.size();
    }
};
class Prize : public Participant {
protected:
    vector <int> places;
    vector<string> prize;
public:
    
    Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize);
    int Get_Data() override{
        cout << "Cont prize" << endl;
        cout << prize.size() << endl;
        return prize.size();
    }
};
Prize::Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize) {
    this->name = name;
    this->surname = surname;
    this->type = type;
    this->age = age;
    this->places = places;
    this->prize = prize;
}
Diploma::Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d){
    this->name = name;
    this->surname = surname;
    this->type = type;
    this->age = age;
    this->places = places;
    this->type_d = type_d;

}
void Sort(Participant* p) {
    Participant temp;
    for (int i = 0; i < 3; i++) {
        for (int j = i + 1; j < 3; j++)
        {
            if (p[j].Get_Data() < p[i].Get_Data()) {
                temp = p[i];
                p[i] = p[j];
                p[j] = temp;
            }
        }

    }
}

int main() {
    Participant* pa[3];
    pa[0] = new Diploma("Alex", "Smith", { "Geo","Math" }, 17, { 1,6 }, { "first"});
    pa[1] = new Prize("Helen", "Blink", { "IT","Math" }, 18, { 2,2 }, {"Golden medal", "medal"});
    pa[2] = new Prize("Brandon", "Brown", { "IT","Math" }, 18, { 2,2 }, { "Golden medal", "medal","gold"});
    Sort(*pa);
    for (int i = 0; i < 3; i++) {
        pa[i]->Get_Data();
        cout << endl;
    }
}
chr
  • 25
  • 4
  • The program has undefined behavior. – Jason May 16 '22 at 15:14
  • 1) There is absolutely no need for user-defined copy constructor and assignment operators for `Participant`. Don't write functions yourself that need not be written, as all you will do is give yourself more chance to introduce bugs. The compiler defaults for those functions are perfectly valid and work 100% of the time. 2) The `Participant` class lacks a virtual destructor, thus if you were to issue `delete` calls in `main`, you would invoke undefined behavior. – PaulMcKenzie May 16 '22 at 15:32
  • @PaulMcKenzie but then how I can sort my objects without assignment operators? Like pa[0]=pa[1]? – chr May 16 '22 at 15:35
  • The assignment operator is used for copying an object to an existing object. It has nothing to do with comparisons or sorting. And also, the compiler will perform `pa[0] = pa[1];` with no problems whatsoever, given the member variable types you are using. They are simply `std::string`, `std::vector` and `int` -- the compiler knows how to copy these safely, efficiently, and without bugs. The compiler will automatically do a member-wise copy on assignment -- you don't need to step in and take over this job when not needed. – PaulMcKenzie May 16 '22 at 15:36
  • Copy constructor and assignment operator are only necessary if the class contains resources that cannot be trusted to copy and assign themselves. Everything in your classes seem to be self-copying. – user4581301 May 16 '22 at 15:37
  • Note: `temp = p[i];` and the other assignments [sliced](https://stackoverflow.com/questions/274626/what-is-object-slicing), but this is made moot by fixing the over-arching problem of passing in the first element rather than the array as is covered by the answer. This is still a duplicate of something though. – user4581301 May 16 '22 at 15:50

1 Answers1

1

The issue here is that when you are passing *pa, only the first element is accessible. If you run it in debug mode you will be able to see that inside sort function, p[1] is not a valid object. Basically, only p[0] is passed to the function. You should pass the reference to the array i.e. **pa to the sort function

void Sort(Participant **p)
{
    Participant *temp;
    for (int i = 0; i < 3; i++)
    {
        for (int j = i + 1; j < 3; j++)
        {
            if (p[j]->Get_Data() < p[i]->Get_Data())
            {
                temp = p[i];
                p[i] = p[j];
                p[j] = temp;
            }
        }
    }
}

int main()
{
    Participant *pa[3];
    pa[0] = new Diploma("Alex", "Smith", {"Geo", "Math"}, 17, {1, 6}, {"first"});
    pa[1] = new Prize("Helen", "Blink", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal"});
    pa[2] = new Prize("Brandon", "Brown", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal", "gold"});
    Sort(pa);
    for (int i = 0; i < 3; i++)
    {
        pa[i]->Get_Data();
        cout << endl;
    }
}
Hammad Ali
  • 168
  • 11