Как выделить память для массива экземпляров, используя абстрактный класс? - PullRequest
3 голосов
/ 15 декабря 2008

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

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();
    }
}

(Извините за любые ошибки, которые я мог совершить, я пишу это на лету, чтобы привести простой пример).

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

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

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

Спасибо, Dan

Ответы [ 3 ]

12 голосов
/ 15 декабря 2008

В этом коде есть только небольшое недоразумение. Вместо того, чтобы размещать объекты Base, вы должны размещать указатели. Указатель может существовать в любое время. Действителен указатель на абстрактный класс, неполный тип и даже 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();
    }
}
6 голосов
/ 15 декабря 2008

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

virtual ~Base();

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

Base** bases = new Base *[10];
5 голосов
/ 15 декабря 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...