У меня есть базовый класс Участник, и мне нужно отсортировать объект в массиве участников по количеству их призов или дипломов. Виртуальная функция get_data возвращает это число. Но пока я пытаюсь отсортировать, у меня возникает ошибка Нарушение прав доступа, выполняющееся в строке со сравнением 2 чисел.
if (p[j].Get_Data() < p[i].Get_Data()) {
Это мой полный код:
#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;
}
}
1) Нет абсолютно никакой необходимости в определяемом пользователем конструкторе копирования и операторах присваивания для Participant
. Не пишите сами функции, которые не нужно писать, так как все, что вы сделаете, это даст себе больше шансов ввести ошибки. Значения компилятора по умолчанию для этих функций вполне допустимы и работают в 100% случаев. 2) В классе Participant
отсутствует виртуальный деструктор, поэтому, если бы вы выполняли вызовы delete
в main
, вы бы вызвали неопределенное поведение.
@PaulMcKenzie, но как я могу сортировать свои объекты без операторов присваивания? Как pa[0]=pa[1]?
Оператор присваивания используется для копирования объекта в существующий объект. Это не имеет ничего общего со сравнениями или сортировкой. Кроме того, компилятор выполнит pa[0] = pa[1];
без каких-либо проблем, учитывая используемые вами типы переменных-членов. Это просто std::string
, std::vector<string>
и int
— компилятор знает, как скопировать их безопасно, эффективно и без ошибок. Компилятор автоматически сделает копию по элементам при назначении - вам не нужно вмешиваться и брать на себя эту работу, когда она не нужна.
Конструктор копирования и оператор присваивания необходимы только в том случае, если класс содержит ресурсы, которым нельзя доверять копирование и присвоение самих себя. Все в ваших классах кажется самокопирующимся.
Примечание: temp = p[i];
и другие назначения нарезанный, но это становится спорным из-за решения общей проблемы передачи первого элемента, а не массива, как описано в ответе. Это все еще дубликат чего-то, хотя.
Проблема здесь в том, что при передаче *pa доступен только первый элемент. Если вы запустите его в режиме отладки, вы сможете увидеть, что внутри функции сортировки p[1] не является допустимым объектом. По сути, в функцию передается только p[0]. Вы должны передать ссылку на массив, т.е. **pa
в функцию сортировки
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;
}
}
Программа имеет неопределенное поведение.