Рассмотрим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <iostream> enum FruitList { AVOCADO, BLACKBERRY, LEMON }; class Fruit { private: FruitList m_type; public: Fruit(FruitList type) : m_type(type) { } FruitList getType() { return m_type; } }; int main() { Fruit avocado(AVOCADO); if (avocado.getType() == AVOCADO) std::cout << "I am an avocado!"; else std::cout << "I am not an avocado!"; return 0; } |
В этой программе всё работает. Но поскольку перечисление FruitList используется в связке с классом Fruit, то немного странно, что оно существует отдельно от самого класса.
Вложенные пользовательские типы данных в классах
В отличие от функций, которые не могут быть вложены (находится внутри друг друга), в языке C++ пользовательские типы данных могут быть определены (вложены) внутри класса. Для этого нужно просто определить пользовательский тип внутри класса под соответствующим спецификатором доступа.
Вот вышеприведенная программа, но уже с FruitList, определенным внутри класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include <iostream> class Fruit { public: // Мы переместили FruitList внутрь класса под спецификатор доступа public enum FruitList { AVOCADO, BLACKBERRY, LEMON }; private: FruitList m_type; public: Fruit(FruitList type) : m_type(type) { } FruitList getType() { return m_type; } }; int main() { // Доступ к FruitList осуществляется через Fruit Fruit avocado(Fruit::AVOCADO); if (avocado.getType() == Fruit::AVOCADO) std::cout << "I am an avocado!"; else std::cout << "I am not an avocado!"; return 0; } |
Обратите внимание:
Во-первых, FruitList теперь определен внутри тела класса.
Во-вторых, мы определили его под спецификатором доступа public, т.е. сделали доступ к FruitList открытым.
По сути, классы работают как пространства имен для любых вложенных типов. В первом примере мы имеем доступ к перечислителю AVOCADO
напрямую, так как AVOCADO
определен в глобальной области видимости (мы могли бы предотвратить это, используя класс enum вместо обычного enum, и тогда доступ к AVOCADO
осуществлялся бы через FruitList::AVOCADO
). Теперь, поскольку FruitList считается частью класса, доступ к перечислителю AVOCADO
осуществляется через имя класса, например: Fruit::AVOCADO
.
Обратите внимание, поскольку классы enum также работают как пространства имен, и если бы мы поместили класс enum (вместо обычного enum) с именем FruitList внутрь класса Fruit, то доступ к перечислителю AVOCADO
осуществлялся бы через Fruit::FruitList::AVOCADO
.
Другие вложенные пользовательские типы данных в классах
Хотя перечисления являются наиболее распространенным вложенным пользовательским типом данных внутри классов, язык C++ также позволяет определять и другие пользовательские типы внутри классов, такие как псевдонимы типов (typedef и type alias) и даже другие классы!
Как и любой обычный член класса, вложенный класс будет иметь доступ ко всем членам класса-оболочки (в котором он размещен). Однако вложенные классы не имеют доступа к указателю *this класса-оболочки.
Определение вложенных типов не очень распространено, но Стандартная библиотека C++ все же использует это в некоторых случаях. Об этом детально мы поговорим на соответствующем уроке.
Если перечисление (или другой тип данных) будет внутри класса, то в каждом объекте будет создаваться одно и тоже перечисление.
Не слишком экономный расход памяти выходит. Правильно ли я понимаю?
Мне кажется, расход памяти будет только если в классе под этот тип выделена переменная (например FruitList m_type; ), от самого по себе вложения типа в класс ничего происходить при создании объекта не будет, эффект будет такой же, как при объявлении перечисления (или иного типа) вне класса. Но я сам тут учусь)
Огромное вам спасибо за ваш труд!
Пожалуйста))
Пожалуйста добавьте тёмный фон, глаза от белого болят
Уже пробовал, тестил и даже на продакшен (сайт Равесли) это всё заливал, но из-за недостаточно эффективного кода реализации, это создавало определенные "микрозадержки" и сбои при переходе/обновлении страниц + на сайте много элементов, фон и цвет которых изменить трудно, так как подключены эти элементы сторонними плагинами или сторонними скриптами. Соответственно, результат получался "лишь частично" (коряво) и свесив все плюсы и минусы, я решил не добавлять данный функционал (кнопка с тёмной версией).
P.S. Пробовал также реализацию ночной темы для сайта через сторонние плагины WordPress — откровенно плохой результат получался. Поэтому данную проблему Вы можете решить пока что только на своей стороне, добавив специальный плагин в Google Chrome (который также далеко не всегда идеально работает).