Как создать массив абстрактного класса с
Иногда возникает необходимость определить класс, который не предполагает создаия конкретных объектов. Например, класс фигуры. В реальности есть конкретные фигуры: квадрат, прямоугольник, треугольник, круг и так далее. Однако абстрактной фигуры самой по себе не существует. В то же время может потребоваться определить для всех фигур какой-то общий класс, который будет содержать общую для всех функциональность. И для описания подобных сущностей используются абстрактные классы.
Абстрактные классы — это классы, которые содержат или наследуют без переопределения хотя бы одну чистую виртуальную функцию. Абстрактный класс определяет интерфейс для переопределения производными классами.
Что такое чистые виртуальные функции (pure virtual functions)? Это функции, которые не имеют определения. Чтобы определить виртуальную функцию как чистую, ее объявление завершается значением «=0». Например, определим абстрактный класс, который представляет геометрическую фигуру:
Класс Figure является абтрактным, потому он содержит как минимум одну чистую виртуальную функцию. А в данном случае даже три таких функции. И ни одна из функций не имеет никакой реализации. Реализацию должны определять классы-наследники.
При этом мы не можем создать объект абстрактного класса:
Определим следующую программу:
Здесь определены два класса-наследника от абстрактного класса Figure — Rectangle (прямоугольник) и Circle (круг). При создании классов-наследников все они должны либо определить для чстых виртуальных функций конкретную реализацию, либо повторить объявление чистой виртуальной функции. Во втором случае производные классы также будут абстрактными.
В данном же случае и Circle, и Rectangle являются конкретными классами и реализуют все виртуальные функции.
Консольный вывод программы:
Стоит отметить, что абстрактный класс может определять и обычные функции и переменные, может иметь несколько конструкторов, но при этом нельзя создавать объекты этого абстрактного класса.
Как создать динамический массив абстрактного класса?
Допустим, у меня есть абстрактный класс Cat, у которого есть несколько конкретных подклассов Wildcat, Housecat и т.д.
Я хочу, чтобы мой массив мог хранить указатели на тип кошки, не зная, какой вид он действительно есть.
Когда я пытаюсь динамически выделять массив Cat, он, похоже, не работает.
4 ответа
Создав aray указателей на Cat, как в
Теперь вы можете поместить ваши экземпляры WildCat, HouseCat и т.д. в различные места в массиве, например
Несколько предостережений, когда они сделаны
a) Не забудьте удалить экземпляры, выделенные в catArray, как в delete catArray [0] и т.д.
b) Не забудьте удалить сам catArray, используя
Вы также должны рассмотреть возможность использования вектора для автоматизации b) для вас
Вам нужно будет создать массив указателей на Cat :
Даже если базовый класс Cat был конкретным, вы все равно будете бегать в срез объектов, если вы создали массив Cat .
Обратите внимание, что вы, вероятно, должны использовать std::vector вместо массива и, вероятно, должны использовать интеллектуальные указатели, чтобы убедиться, что ваш код является безопасным.
Вы не можете округлить кошек в клетках фиксированного размера, потому что компилятор не знает, насколько велики будут кошки, и (сбой метафоры), как их инициализировать. Вам нужно будет сделать что-то вроде инициализации массива нулевыми кошачьими указателями или чем-то еще, а потом их ставить.
Вы не можете напрямую создать экземпляр абстрактного класса, но вместо этого необходимо создать экземпляр полностью реализованного подкласса.
Итак, это законно:
а затем вы можете получить доступ к каждой кошке через интерфейс Cat
Но компилятор не знает, как создать экземпляр абстрактного класса; фактически, тот факт, что он абстрактный, означает, что он не может быть непосредственно создан.
Зачем? Поскольку у Cat будет абстрактный метод
Чтобы все унаследованные кошки были реализованы. Затем вы можете спросить, может ли он мяукать, с вероятностью, что экземпляр Lion вернет false.
How to create a dynamic array of an Abstract class?
Lets say I have an abstract class Cat that has a few concrete subclasses Wildcat, Housecat, etc.
I want my array to be able to store pointers to a type of cat without knowing which kind it really is.
When I try to dynamically allocate an array of Cat, it doesn’t seem to be working.
5 Answers 5
By creating an aray of pointers to Cat, as in
Now you can put your WildCat, HouseCat etc instances at various locations in the array for example
Couple of caveats, when done
a) Don’t forget deleting the instances allocated in catArray as in delete catArray[0] etc.
b) Don’t forget to delete the catArray itself using
You should also consider using vector to automate b) for you
You would need to create an array of pointers to Cat :
Even if the base class Cat was concrete, you would still run headlong into object slicing if you created an array of Cat .
Note that you should probably use a std::vector instead of an array, and should probably use smart pointers to ensure your code is exception safe.
![]()
You cannot round up the cats in fixed size cages, because the compiler has no way of knowing how big the cats will be, nor (metaphor failure) how to initialize them. You are going need to do something like initialize the array to null cat-pointers or something, and herd them later.
![]()
You cannot directly instantiate an instance of an abstract class, but must instead instantiate an instance of a fully implemented subclass.
So this is legal:
and then you can access each cat through the Cat interface
But the compiler has no way of knowing how to instantiate an abstract class; in fact, the very fact that it’s abstract means that it cannot be directly instantiated.
Why do this? Because Cat will have an abstract method
That all inherited cats must implement. Then you can ask if it can meow, with the chance that an instance of Lion will return false.
Something I did in a similar case was then to loop through the array and point each element to nullptr. That way you can easily check whether you’ve added a derived class object to a slot or if it’s open.
I wonder if there’s an easier way to do this, to check whether an element in an array of pointers to an abstract class points to an object of a derived class or is just an abstract pointer, without setting the element to nullptr. Like, is there a bool IsObject(ObjectType* ptr) or something in the standard library?
And, I wonder if setting each element to nullptr poses any potential problems, other than the computing cost of looping through the array and setting them to nullptr.
I posted this as an independent question (Array of Pointers to an Abstract Class: to nullptr or not to nullptr (C++)), but I thought it might be relevant here since this post is the closest to my question that I found when searching.
Как создать динамический массив абстрактного класса?
Допустим, у меня есть абстрактный класс Cat, который имеет несколько конкретных подклассов Wildcat, Housecat и т. Д.
Я хочу, чтобы в моем массиве можно было хранить указатели на тип кошки, не зная, какой это тип на самом деле.
Когда я пытаюсь динамически выделить массив Cat, похоже, это не работает.
5 ответы
Создавая ряд указателей на Cat, как в
Теперь вы можете разместить свои экземпляры WildCat, HouseCat и т. Д. В различных местах массива, например.
Несколько предостережений, когда закончите
a) Не забудьте удалить экземпляры, выделенные в catArray, как в delete catArray [0] и т. д.
б) Не забудьте удалить сам catArray, используя
Вам также следует подумать об использовании вектора для автоматизации b) для вас
ответ дан 27 апр.
Вам нужно будет создать массив указателей на Cat :
Даже если базовый класс Cat был конкретным, вы бы все равно врезались в нарезка объекта если вы создали массив Cat .
Обратите внимание, что вам, вероятно, следует использовать std::vector вместо массива и, вероятно, следует использовать интеллектуальные указатели, чтобы гарантировать, что ваш код безопасен в отношении исключений.
ответ дан 23 мая ’17, 13:05

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

Вы не можете напрямую создать экземпляр абстрактного класса, вместо этого необходимо создать экземпляр полностью реализованного подкласса.
Итак, это законно:
а затем вы можете получить доступ к каждой кошке через интерфейс Cat
Но компилятор не знает, как создать экземпляр абстрактного класса; Фактически, тот факт, что он абстрактный, означает, что он не может быть создан напрямую.
Зачем это делать? Потому что у Cat будет абстрактный метод
Это должны реализовывать все унаследованные кошки. Затем вы можете спросить, может ли он мяукать, с вероятностью, что экземпляр Lion вернет false.
ответ дан 27 апр.
Что-то, что я сделал в аналогичном случае, заключалось в том, чтобы затем перебрать массив и указать каждому элементу nullptr. Таким образом, вы можете легко проверить, добавили ли вы объект производного класса в слот или он открыт.
Интересно, есть ли более простой способ сделать это, чтобы проверить, указывает ли элемент в массиве указателей на абстрактный класс на объект производного класса или это просто абстрактный указатель, не устанавливая для элемента значение nullptr. Мол, есть ли bool IsObject (ObjectType * ptr) или что-то в стандартной библиотеке?
И мне интересно, создает ли установка для каждого элемента значения nullptr какие-либо потенциальные проблемы, кроме затрат на вычисление цикла по массиву и установки для них значения nullptr.
Я разместил это как самостоятельный вопрос (Массив указателей на абстрактный класс: на nullptr или не на nullptr (C ++)), но я подумал, что это может быть уместно здесь, поскольку этот пост является наиболее близким к моему вопросу, который я нашел при поиске.
На самом деле, похоже, есть несоответствие размера памяти. Работаю над выяснением этого. — Калеб Коберли
Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками c++ arrays abstract-class abstract or задайте свой вопрос.