Вызвать можно как
myFishes[0] = new Tuna();
так и не указывая скобок
myFishes[0] = new Tuna;
, для приведённого примера, где Tuna - это с++ класс, имеющий конструктор без параметров. Вызов со скобками Tuna() - это явный вызов конструктора. Разницы при этом не будет, конструктор класса и так будет вызван в обоих случаях.
Если бы класс Tuna не имел бы такого безпараметрного конструктора, а требовал бы одного, двух или более параметров, то пришлось вызывать бы
myFishes[0] = new Tuna(1, 2, "param3"); // Или с другими значениями, в зависимости от объявления
а вызов new без скобок просто не работал.
> мы выделяем память для каждого класса и присваиваем адрес ячейки памяти каждому элементу массива?
Массив хранит только адреса, указывающие на экземпляры созданных классов, сами экземпляры в данном случае могут лежать в произвольных кусочках памяти.
#include <iostream>
using namespace std;
class Fish
{
public:
virtual Fish* Clon() = 0;
virtual void Swim() = 0;
virtual ~Fish() {};
};
class Tuna : public Fish
{
public:
Fish* Clon() override
{
return new Tuna(*this);
}
void Swim() override final
{
cout << "Тунец быстро плавает"
" в море!\n";
}
};
class BluefinTuna : public Tuna
{
public:
Fish* Clon() override
{
return new BluefinTuna(*this);
}
// void Swim()
};
class Carp final : public Fish
{
Fish* Clon() override
{
return new Carp(*this);
}
void Swim() override final
{
cout << "Карп медленно плавает"
" в озере!\n";
}
};
int main()
{
setlocale(LC_ALL, "ru");
const int ARRAY = 4;
Fish* myFishes[ARRAY] = { nullptr };
myFishes[0] = new Tuna();
myFishes[1] = new Carp();
myFishes[2] = new BluefinTuna();
myFishes[3] = new Carp();
Fish* MyNewFishes[ARRAY];
for (int end = 0; end < ARRAY; ++end)
{
MyNewFishes[end] = myFishes[end]->Clon();
}
for (int end = 0; end < ARRAY; ++end)
{
MyNewFishes[end]->Swim();
}
for (int end = 0; end < ARRAY; ++end)
{
delete myFishes[end];
delete MyNewFishes[end];
}
return 0;
}