A
A
Alexander Markelov2021-10-27 23:24:08
OOP
Alexander Markelov, 2021-10-27 23:24:08

How to delete all derived class objects by common field in dynamic array?

An array of abstract class type pointers to elements of inherited classes is given. One of the menu items is deleting objects by the common field Destination, when I try to delete, I encounter an error.

Interested in the Delete function .
I will also be glad to comments on inheritance and code design!

The code
#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;
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
Wataru, 2021-10-27
@lucky_bastard

You have such a mess there... Rewrite using std::vector. When you try to use class pointers and pointers like arrays at the same time, you get confused.
Now you are passing the first element of the array (its value) to Delete, not a pointer to the element itself, like an array. Further, even if you correct it to an array of pointers, the change inside the Delete function will not be visible from the outside, because you simply overwrite the pointer passed by value. If you really want to work with Sish arrays, then you will have to pass a pointer-to-pointer-to-pointer there. Shit code turns out, pass a link to a vector of pointers.
Use the override keyword wherever you want to override methods in an inherited class, then the compiler will point you to errors in your code.
Well, why do you need a virtual GetDest if it is not overloaded by the heir anywhere?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question