За и против использования вложенных классов C++ и перечислений?

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

44
задан JasonMArcher 7 June 2015 в 01:24
поделиться

9 ответов

Вложенные классы

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

Позволяют нам вообразить следующий код:

class A
{
   public :
      class B { /* etc. */ } ;

   // etc.
} ;

Или даже:

class A
{
   public :
      class B ;

   // etc.
} ;

class A::B
{
   public :

   // etc.
} ;

Так:

  • Доступ Privilegied: А:: B имеет privilegied доступ ко всем членам (методы, переменные, символы, и т.д.), который ослабляет инкапсуляцию
  • , объемом А является кандидат на поиск символа: код из B будет видеть весь символы от как возможные кандидаты на поиск символа, который может перепутать код
  • предописание: нет никакого способа передать - объявляют A:: B, не давая полное объявление
  • Расширяемость: невозможно добавить другой класс A:: C, если Вы не владелец
  • многословие Кода: классы помещения в классы только делает заголовки больше. Можно все еще разделить это на многократные объявления, но нет никакого способа использовать подобные пространству имен псевдонимы, импорт или использования.

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

, Кроме того, это пахнет как неуклюжая попытка моделировать пространство имен, не используя пространства имен 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 ;

точно для этого вида проблем.

44
ответ дан paercebal 26 November 2019 в 22:16
поделиться

2008 Visual Studio, кажется, не в состоянии обеспечить intellisense для вложенных классов, таким образом, я переключился на идиому PIMPL в большинстве случаев, где я раньше имел вложенный класс. Я всегда помещал перечисления или в класс, если он используется только тем классом, или вне класса в том же пространстве имен как класс, когда больше чем один класс использует перечисление.

0
ответ дан Brian Stewart 26 November 2019 в 22:16
поделиться

Если Вы помещаете перечисление в класс, или пространство имен, intellisense будет в состоянии дать Вам указания, когда Вы попытаетесь помнить перечислимые имена. Мелочь наверняка, но иногда вопрос мелочей.

0
ответ дан Mark Ransom 26 November 2019 в 22:16
поделиться

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

Так, да, встраивают перечисление в класс, если другой код только использует то перечисление для взаимодействия через интерфейс непосредственно с тем реальным классом. Иначе найдите, что лучшее место сохраняет перечисление, такое как пространство имен.

0
ответ дан Pat Notz 26 November 2019 в 22:16
поделиться

Для меня большой довод "против" к наличию снаружи случается так, что это становится частью глобального пространства имен. Если перечисление или связанный класс только действительно относятся к классу, в котором это находится, то это имеет смысл. Таким образом в случае принтера, все, что включает принтер, будет знать о наличии полного доступа к перечислимому PRINTER_TYPE, где это не должно действительно знать об этом. Я не могу сказать, что когда-либо использовал внутренний класс, но для перечисления, это кажется более логичным для держания его внутри. Как другой плакат указал, это - также хорошая идея использовать пространства имен для группировки подобных объектов, начиная с засорения глобального пространства имен может действительно быть плохая вещь. Я ранее работал над проектами, которые являются крупными и просто поднимают, автоматический полный список на глобальном пространстве имен занимает 20 минут. По-моему, вложенные перечисления и namespaced классы/структуры являются, вероятно, самым чистым подходом.

0
ответ дан DavidG 26 November 2019 в 22:16
поделиться

paercebal сказал все, что я скажу о вложенных перечислениях.

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

Так, например, если у меня был printer_manipulator класс, он мог бы иметь содержавший класс для ошибок управления принтером, но сам принтер будет не содержавшим классом.

Hope это помогает.:)

1
ответ дан Nick 26 November 2019 в 22:16
поделиться

Кажется, что необходимо использовать пространства имен вместо классов для группировки как вещи, которые связаны друг с другом таким образом. Один довод "против", который я видел в выполнении вложенных классов, является Вами, заканчиваются с действительно большим исходным файлом, который мог быть трудным к grok, когда Вы ищете раздел.

2
ответ дан carson 26 November 2019 в 22:16
поделиться

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

Это - когда Вы хотите использовать "внутренний" класс в качестве объекта самостоятельно, что вещи могут начать становиться немного гадкими, и необходимо начать писать стандартные программы экстрактора/вставки. Не симпатичная ситуация.

2
ответ дан Paul Nathan 26 November 2019 в 22:16
поделиться

Один довод "против", который может стать грандиозным предприятием для крупных проектов, - то, что невозможно сделать предописание для вложенных классов или перечислений.

6
ответ дан Adam Rosenfield 26 November 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: