Как удалить все объекты производных классов по общему полю в динамическом массиве?

Дан массив указателей типа абстрактного класса на элементы наследуемых классов. Один из пунктов меню удаление объектов по общему полю Пункт Назначения, при попытке удаления сталкиваюсь с ошибкой.

Интересует функция Delete.
Буду рад также замечаниям по наследованию и оформлению кода!
Код
#include <iostream>
#include <string>
#include <cstring>
using namespace std;


class Train
{
public:
	virtual void GetAll() = 0;
	virtual string GetDest() = 0;
	virtual int GetPrice() = 0;
	virtual void SetAll() = 0;

};

class Based : public Train
{
protected:
	int price;
	string dest;
private:
	int pas_number;
	string dep_time;

public:

	Based(string dest, string dep_time, int pas_number, int price)
	{
		this->dest = dest;
		this->dep_time = dep_time;
		this->pas_number = pas_number;
		this->price = price;
	}

	Based()
	{
		dest = "---";
		dep_time = "---";
		pas_number = 0;
		price = 0;
		cout << "Вызов конструктор Based" << endl;
	}

	int GetPas()
	{
		return pas_number;
	}
	void SetPas()
	{
		cout << "Количество пассажиров:";
		cin >> pas_number;
	}

	string GetTime()
	{
		return dep_time;
	}

	void SetTime()
	{
		cout << "Время отправления:";
		cin >> dep_time;
	}
	void GetAll()
	{
		cout << "\nПункт назначения:" << dest << endl;
		cout << "Цена билета:" << price << " лей" << endl;
		cout << "Время отправления:" << dep_time << endl;
		cout << "Количество пассажиров:" << pas_number << endl;
	}
	void SetAll()
	{
		SetDest();
		SetTime();
		SetPas();
		SetPrice();
	}

	string GetDest()
	{
		return dest;
	}
	void SetDest()
	{
		cout << "Пункт назначения:";
		cin >> dest;
	}
	void SetPrice()
	{
		cout << "Цена билета(в леях):";
		cin >> price;
	}

	int GetPrice()
	{
		return price;
	}

	~Based()
	{
		cout << "Уничтожение объекта Based" << endl;
	}
};
class TrainEC : public virtual Based
{
protected: int numb_places; // кол-во мест
private: string dest_time; //время прибытия
public:
	~TrainEC()
	{
		cout << "Уничтожение объекта TrainEC" << endl;
	}

	TrainEC()
	{
		numb_places = 0;
		dest_time = "null";
		dest = "---";
		price = 0;
		cout << "Вызов конструктора TrainEC" << endl;
	}

	TrainEC(int numb, string dest, int pr, string dest_place)
	{

		numb_places = numb;
		dest_time = dest;
		dest = dest_place;
		price = pr;

	}

	void SetPlaces()
	{
		cout << "Введите кол-во мест в поезде:"; cin >> numb_places;
	}

	int GetPlaces()
	{
		return numb_places;
	}

	void SetDestTime()
	{
		cout << "Введите время прибытия поезда:"; cin >> dest_time;
	}

	string GetDestTime()
	{
		return dest_time;
	}

	void SetAll()
	{
		SetPrice();
		SetDest();
		SetDestTime();
		SetPlaces();
	}

	void GetAll()
	{
		cout << "\nПункт назначения:" << GetDest() << endl;
		cout << "Цена билета:" << GetPrice() << "лей" << endl;
		cout << "Время прибытия:" << GetDestTime() << endl;
		cout << "Кол-во мест:" << GetPlaces() << endl;
	}

};

class TrainBU : public virtual Based
{
protected: string food; //еда, напитки
private: string clothes; //постельное белье
public:
	~TrainBU()
	{
		cout << "Вызов деструктора TrainBU" << endl;
	}

	TrainBU()
	{
		food = "---";
		clothes = "---";
		dest = "---";
		price = 0;
		cout << "Вызов конструктора TrainBU" << endl;
	}

	TrainBU(string food_inf, string clothes_inf, string dest_place, int pr)
	{
		food = food_inf;
		clothes = clothes_inf;
		dest = dest_place;
		price = pr;
	}

	void SetFood()
	{
		cout << "Введите опцию для заказа еды (есть/нет):"; cin >> food;
	}

	string GetFood()
	{
		return food;
	}

	void SetCloth()
	{
		cout << "Введите опцию для наличия постельного белья (есть/нет):"; cin >> clothes;
	}

	string GetCloth()
	{
		return clothes;
	}

	void SetAll()
	{
		SetDest();
		SetPrice();
		SetFood();
		SetCloth();
	}
	void GetAll()
	{
		cout << "\nПункт назначения:" << GetDest() << endl;
		cout << "Цена билета:" << GetPrice() << " лей" << endl;
		cout << "Наличие еды:" << GetFood() << endl;
		cout << "Наличие постельного белья:" << GetCloth() << endl;
	}

};

class TrainMix : public TrainEC, public TrainBU
{
private:
	string alco;
public:
	~TrainMix()
	{
		cout << "Вызов деструктора TrainMix" << endl;
	}

	TrainMix()
	{
		dest = "---";
		price = 0;
		numb_places = 0;
		food = "---";
		alco = "---";
		cout << "Вызов конструктора TrainMix" << endl;
	}

	TrainMix(string dest_place, int pr, int places, string food1, string alco1)
	{
		dest = dest_place;
		price = pr;
		numb_places = places;
		food = food1;
		alco = alco1;
	}

	void SetAlco()
	{
		cout << "Введите опцию наличия еды (есть/нет):"; cin >> alco;
	}
	string GetAlco()
	{
		return alco;
	}

	void SetAll()
	{
		SetDest();
		SetPrice();
		SetPlaces();
		SetFood();
		SetAlco();

	}

	void GetAll()
	{
		cout << "\nПункт назначения" << GetDest() << endl;
		cout << "Цена билета:" << GetPrice() << endl;
		cout << "Кол-во мест:" << GetPlaces() << endl;
		cout << "Наличие еды:" << GetFood() << endl;
		cout << "Наличие алкоголя:" << GetAlco() << endl;
	}

};

void CreateArray(Train* train[], const int SIZE)
{
	for (int i = 0; i < SIZE; i++)
	{
		switch (i % 4)
		{
		case 0: train[i] = new Based; break;
		case 1: train[i] = new TrainEC; break;
		case 2: train[i] = new TrainBU; break;
		case 3: train[i] = new TrainMix; break;
		}
		train[i]->SetAll();
	}
}

void Input(Train* train[], int& size)
{
	int answer;
	cout << "Введите поезд тип поезда, который вы хотите добавить( Based - 1, TrainEC - 2, TrainBU - 3, Train Mix - 4 :"; cin >> answer;

	switch (answer)
	{
	case 1: train[size] = new Based; break;
	case 2: train[size] = new TrainEC; break;
	case 3: train[size] = new TrainBU; break;
	case 4: train[size] = new TrainMix; break;
	}
	train[size]->SetAll();
	size++;
}

void Output(Train* train[], int& size)
{
	for (int i = 0; i < size; i++)
		train[i]->GetAll();
}

void Sort(Train* train[], int& size)
{
	Train* temp;

	for (int i = 0; i < size; i++)
		for (int j = i + 1; j < size; j++)
			if (train[i]->GetPrice() > train[j]->GetPrice())
			{
				temp = train[i];
				train[i] = train[j];
				train[j] = temp;
			}
}

void OutputCondition(Train* train[], int& size)
{
	string answer;
	cout << "Введите пункт назначения для которого вы хотите вывести поезд:"; cin >> answer;
	for (int i = 0; i < size; i++)
	{
		if (train[i]->GetDest() == answer)
			train[i]->GetAll();
	}
}

void ChangeInfo(Train* train[])
{
	int POSITION;
	cout << "Введите позицию на которой вы хотите изменить данные:"; cin >> POSITION;
	train[POSITION - 1]->SetAll();
}

void Delete(Train *train, int& size)
{
	string dest;
	int n=0;

	cout << "\nВведите пункт назначения для удаления поезда:" << endl; cin >> dest;
	for (int i = 0; i < size; i++)
		if (train[i].GetDest() == dest) // <-- Вот тут исключение: нарушение доступа к `train` на чтение.
			++n;
	Train* newarray = new Based[size - n];

	for (int i = 0, j = 0; i < size; i++)
	{
		if (train[i].GetDest() == dest)
		{
			j++;
			continue;
		}
		else
			newarray[i - j] = train[i];
	}
	size -= n;
	delete[] train;
	train = newarray;
}


int main()
{
	int size;
	setlocale(LC_ALL, "ru");
	cout << "Введите количество элементов массива:"; cin >> size;
	Train* train[40];
	CreateArray(train, size);


	int choice;

	do {
		do
		{
			cout << "\nГлавное меню:" << endl;
			cout << "1.Чтение с клавиатуры значений элементов объектов разных классов из иерархии в заданном массиве;" << endl;
			cout << "2.Отобразить на экране объекты массива;" << endl;
			cout << "3.Сортировка объектов по цене билета в порядке возрастания;" << endl;
			cout << "4.Вывод на экран поездов, для которых известен пункт назначения введенный с клаиватуры" << endl;
			cout << "5.Изменить данные объекта на позицию k в массиве объектов (k читается с клавиатуры);" << endl;
			cout << "6.Удаляется объект, для которого известно, что общее поле для всех классов в иерархии, удовлетворяет условию сформулированному студентом." << endl;
			cout << "7.Выход" << endl;
			cout << "Ваш выбор:" << endl;
			cin >> choice;

		} while (choice < 1 || choice > 7);

		switch (choice)
		{
		case 1: Input(train, size); break;
		case 2: Output(train, size); break;
		case 3: Sort(train, size); break;
		case 4: OutputCondition(train, size); break;
		case 5: ChangeInfo(train); break;
		case 6: Delete(*train, size); break;
		case 7: cout << "Спасибо! Удачи!" << endl; break;
		default: cout << "Ошибка!" << endl;
		}
	} while (choice != 7);


	return 0;
}
  • Вопрос задан
  • 97 просмотров
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
У вас там такая мешанина... Перепишите с использованием std::vector. Когда вы пытаетесь одновременно использовать указатели на классы и указатели, как массивы, вы все путаете.

Сейчас вы в Delete передаете первый элемент массива (его значение), а не указатель на сам элемент, как массив. Далее, даже если вы там исправите на массив указателей, изменение внутри функции Delete снаружи видны не будут, потому что вы просто переписываете переданный по значению указатель. Если уж хотите с Сишными массивами работать, то вам там придется передавать указатель-на-указатель-на-указатель. Говнокод же получается, передавайте ссылку на вектор указателей.

Используйте ключевое слово override везде, где вы хотите переопределить методы в унаследованном классе, тогда вам компилятор укажет на ошибки в вашем коде.

Ну и зачем вам виртуальное GetDest, если оно нигде не перегружается наследником?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы