Как выделить память для массива экземпляров с помощью абстрактного класса?

StackOverflow https://stackoverflow.com/questions/368976

  •  21-08-2019
  •  | 
  •  

Вопрос

У меня есть абстрактный класс, определяющий чистый виртуальный метод в С++:

class Base
{
Base();
~Base();

virtual bool Test() = 0;
};

Я разделил его на несколько других классов (которые обеспечивают реализацию Test()), которые я буду называть A, B, C и т. д.Теперь я хочу создать массив любого из этих типов, используя этот базовый класс:

int main(int argc, char* argv[])
{
    int size = 0;
    Base* bases = new Base[10];

    bases[size++] = new A();
    bases[size++] = new B();

    for (int i = 0; i < size; i++)
    {
        Base* base = bases[i];
        base->Test();
    }
}

(Прошу прощения за возможные ошибки, я пишу это на лету, чтобы продемонстрировать простой пример).

Проблема в том, что я не могу создать экземпляр массива, поскольку для этого потребуется создать экземпляр базового класса (чего он не может сделать, поскольку он абстрактный).Однако без этого он не выделил бы память, необходимую для присвоения индексам массива, и, таким образом, возникнет ошибка сегментации при попытке доступа к этой памяти.У меня сложилось впечатление, что смешивать новое и удаление с malloc и free - не очень хорошая практика.

Возможно, я запутался в том, как это следует использовать, и мне следует попытаться использовать для этого шаблоны или какой-либо другой механизм, но, надеюсь, я предоставил достаточно информации, чтобы проиллюстрировать то, что я пытаюсь сделать.

Итак, как лучше всего это сделать и как обойти проблему выделения памяти абстрактному классу?

Спасибо, Дэн

Это было полезно?

Решение

В этом коде есть лишь небольшое недоразумение.Вместо выделения базовых объектов вам необходимо выделить указатели.Указатель может существовать в любое время.Указатель на абстрактный класс, на неполный тип и даже на void допустим:

int main(int argc, char* argv[])
{
    int size = 0;
    Base** bases = new Base*[10];

    bases[size++] = new A();
    bases[size++] = new B();

    for (int i = 0; i < size; i++)
    {
        Base* base = bases[i];
        base->Test();
    }
}

Другие советы

Во-первых, убедитесь, что ваш деструктор также объявлен как виртуальный:

virtual ~Base();

Вам лучше хранить массив указателей на экземпляры:

Base** bases = new Base *[10];

Массив предполагает, что все его элементы имеют одинаковый размер.Если у вас есть классы C++, производные от одной базы, экземпляры могут быть любого размера.Таким образом, независимо от того, является база абстрактной или нет, вы не можете выделить массив базовых экземпляров, а затем поместить туда производные экземпляры.

Как говорят другие ответы, вам нужно использовать указатели.Выделите массив указателей для базы, а затем выделите различные производные экземпляры и сохраните указатели на них в массиве.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top