Есть основной класс 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
2 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
Подскажите, что нужно исправить, чтобы заработало. Или может это можно сделать как-то по-другому?
Ответ
Переменная 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
И еще лучше использовать умные указатели
#include
//...
std::vector
В этом случае вам не надо беспокоиться об освобождении памяти и вызовах деструкторов объектов.
Имейте в виду, что в C++ функция main без параметров должна быть объявлена как
int main()
то есть она должна иметь тип возвращаемого значения int
Кроме того ваша программа содержит баг, так как в случае, когда пользователь в цикле введет неверное значение, то есть ни 1 и ни 2, то элемент массива останется не инициализированным и пропущенным.
По крайней мере вам следует ввод значения также заключить в цикл. Например,
do
{
cout << "1 for Human
2 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, не так ли?:)
Комментариев нет:
Отправить комментарий