Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

Массив с разными типами данных

#cpp #массивы #классы #указатели #наследование


Есть основной класс Human, есть наследуемый от него Doctor. Нужно сделать массив,
в котором будут как объекты первого класса, так и второго. Я своим скудным умишкой
додумался только до этого.

#include "Human.h"
#include "Doctor.h"

using namespace std;

void main() {

int n = 0;
cout << "How many? ";
cin >> n;
int m;
Human **uni;
ofstream fout("humans.txt", ios::app);

for (int i = 0; i < n; i++) {
    cout << "1 for Human\n2 for Doctor ";
    cin >> m;
    switch (m) {
    case 1: {
                uni[i] = new Human(); \\в этой строке возникает ошибка
                uni[i]->Set(cin);
                uni[i]->InFile(fout);
                break;
    }
    case 2: {
                uni[i] = new Doctor();
                uni[i]->Set(cin);
                uni[i]->InFile(fout);
                break;
    }
        default: cout << "Wrong input."; system("pause");
              }
    }
}


Но вылазит ошибка:


  Error 1   error C4700: uninitialized local variable


Подскажите, что нужно исправить, чтобы заработало. Или может это можно сделать как-то
по-другому?
    


Ответы

Ответ 1



Переменная uni объявлена, но не инициализирована Human **uni; Поэтому использования случайного значения этой переменной в предложениях uni[i] = new Human(); и uni[i] = new Doctor(); ведет к неопределенному поведению программы, о чем компилятор вам любезно сообщил. Вам сначала надо выделить память под массив указателей на базовый класс uni = new Human *[n]; и только затем вы можете инициализировать элементы этого массива в предложениях uni[i] = new Human(); и uni[i] = new Doctor(); Также вы должны не забыть освободить всю выделенную память в обратном порядке, когда массив объектов больше вам будет не нужен. В подобных случаях лучше использовать стандартный класс std::vector. Например, #include //... std::vector uni; И еще лучше использовать умные указатели #include #include //... std::vector> uni; В этом случае вам не надо беспокоиться об освобождении памяти и вызовах деструкторов объектов. Имейте в виду, что в C++ функция main без параметров должна быть объявлена как int main() то есть она должна иметь тип возвращаемого значения int. Кроме того ваша программа содержит баг, так как в случае, когда пользователь в цикле введет неверное значение, то есть ни 1 и ни 2, то элемент массива останется не инициализированным и пропущенным. По крайней мере вам следует ввод значения также заключить в цикл. Например, do { cout << "1 for Human\n2 for Doctor "; cin >> m; } while ( m != 1 && m != 2 ); И только после этого цикла размещать switch предложение. Также вместо магических чисел 1 и 2 лучше объявить перечисление. Например enum { HUMAN = 1, DOCTOR = 2 }; и использовать эти константы в switch предложении switch (m) { case HUMAN: { uni[i] = new Human(); \\в этой строке возникает ошибка uni[i]->Set(cin); uni[i]->InFile(fout); break; } case DOCTOR: { uni[i] = new Doctor(); uni[i]->Set(cin); uni[i]->InFile(fout); break; } //... Надеюсь, что деструктор базового класса объявлен со спецификатором функции virtual, не так ли?:)

Ответ 2



Надо для массива память выделить. Human **uni = new Human*[n];

Комментариев нет:

Отправить комментарий