Вложенные классы
Есть несколько побочных эффектов для классов, вложенных в классы, которые я обычно считаю недостатками (если не чистыми антипаттернами).
Давайте представим следующий код:
class A
{
public :
class B { /* etc. */ } ;
// etc.
} ;
Или даже:
class A
{
public :
class B ;
// etc.
} ;
class A::B
{
public :
// etc.
} ;
Итак:
- Привилегированный доступ: A :: B имеет привилегированный доступ ко всем членам A (методам, переменным, символам и т. Д.), Что ослабляет инкапсуляцию
- Область A является кандидатом для поиска символов: код изнутри B увидит все символы из A в качестве возможных кандидатов для поиска символов, что может привести к путанице в коде
- форвард-декларация: Невозможно форвард-декларировать A :: B без полного объявления A
- Расширяемость: Невозможно добавить другой класс A :: C, если вы не являетесь владельцем A
- Детализация кода: размещение классов в классах только увеличивает заголовки. Вы все еще можете разделить это на несколько объявлений, но нет никакого способа использовать псевдонимы, импорт или использование, подобные пространству имен.
В заключение, за исключением исключений (например, вложенный класс является неотъемлемой частью класса вложенности ... И даже тогда ...), я не вижу смысла во вложенных классах в нормальном коде, поскольку недостатки перевешивают на величины Воспринимаемые преимущества.
Кроме того, он пахнет неуклюжей попыткой симулировать пространство имен без использования пространств имен C ++.
На стороне поддержки вы изолируете этот код, а если он частный, сделаете его непригодным для использования, но из "внешнего" класса ...
Вложенные перечисления
Плюсы: все.
Con: Ничего.
Дело в том, что перечисленные элементы будут загрязнять глобальный охват:
// collision
enum Value { empty = 7, undefined, defined } ;
enum Glass { empty = 42, half, full } ;
// empty is from Value or Glass?
Ony, поместив каждое перечисление в отдельное пространство имен / класс, позволит вам избежать этого столкновения:
namespace Value { enum type { empty = 7, undefined, defined } ; }
namespace Glass { enum type { empty = 42, half, full } ; }
// Value::type e = Value::empty ;
// Glass::type f = Glass::empty ;
Обратите внимание, что C ++ 0x определил перечисление класса:
enum class Value { empty, undefined, defined } ;
enum class Glass { empty, half, full } ;
// Value e = Value::empty ;
// Glass f = Glass::empty ;
именно для такого рода проблем.