Страницы

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

среда, 3 апреля 2019 г.

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

Есть основной класс 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 uni;
И еще лучше использовать умные указатели
#include #include
//...
std::vector> uni;
В этом случае вам не надо беспокоиться об освобождении памяти и вызовах деструкторов объектов.
Имейте в виду, что в 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, не так ли?:)

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

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