В
Animal **arr = new Animal*[10];
Animal **arr
объявляет указатель на указатель. new Animal*[10]
выделяет 10 указателей на Animal
с. Эти 10 указателей не инициализированы и нигде не безопасны для использования.
arr[0]->getAge();
получает первые 10 указателей и пытается использовать то, на что указывает. Поскольку он не указывает на действительный Animal
, все может произойти. В этом случае оказывается, что программа вылетает. Это один из лучших результатов, потому что он сразу делает ошибку заметной.
Теперь предположим, что Tiger
происходит от Animal
class Tiger: public Animal
{
// definition of Tiger
}
тогда можно позже
arr[0] = new Tiger;
чтобы указать первый из 10 указателей на действительный экземпляр Tiger
, а затем вы можете
arr[0]->getAge();
Когда вы закончите, не забудьте delete
все Animal
s и delete[]
arr
.
Sidenote:
Не пишите такой код. Это чрезвычайно подвержен ошибкам. Вместо этого используйте преимущества контейнеров стандартной библиотеки, таких как std::vector
, и предпочитайте умные указатели, такие как std::unique_ptr
, для управления динамической памятью программы. Пример: * * тысяча тридцать пять
std::vector<std::unique_ptr<Animal>> arr;
Создает массив с изменяемым размером Animal
с, который будет автоматически удаляться, когда arr
больше не нужен и выходит из области видимости.
Добавление Tiger
будет выглядеть как
arr.push_back(std::make_unique<Tiger>());
Это выглядит более громоздким, но избавляет вас от необходимости искать точные места в коде, где вы должны delete
свои ресурсы, и быть абсолютно уверенным, что они delete
d.