Различие между перечислением и определяет операторы

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
45
задан Brian Tompsett - 汤莱恩 31 January 2016 в 17:29
поделиться

15 ответов

enum определяет синтаксический элемент.

#define предварительная директива препроцессору, выполняемая прежде , компилятор видит код, и поэтому не является элементом языка самого C.

Обычно перечисления предпочтены, поскольку они безопасные с точки зрения типов и более легко поддающимися обнаружению. Определяет более тверды расположиться и может иметь сложное поведение, например, одна часть кода может переопределить #define сделанный другим. Это может быть трудно разыскать.

57
ответ дан Jason Cohen 26 November 2019 в 21:03
поделиться

Другое преимущество перечисления по списку определяет, то, что компиляторы (gcc, по крайней мере) могут генерировать предупреждение, что если не все значения проверяются в операторе переключения. Например:

enum {
    STATE_ONE,
    STATE_TWO,
    STATE_THREE
};

...

switch (state) {
case STATE_ONE:
    handle_state_one();
    break;
case STATE_TWO:
    handle_state_two();
    break;
};

В предыдущем коде, компилятор в состоянии генерировать предупреждение, что не все значения перечисления обрабатываются в переключателе. Если бы состояния были сделаны как #define, это не имело бы место.

1
ответ дан Russell Bryant 26 November 2019 в 21:03
поделиться

В дополнение к упомянутым выше положительным сторонам можно ограничить объем перечислений к классу, структуре или пространству имен. Лично, мне нравится иметь минимальное количество соответствующих символов в объеме в любой момент, который является другой причиной использования перечислений, а не #defines.

1
ответ дан SmacL 26 November 2019 в 21:03
поделиться

Если бы у Вас есть группа констант (как "Дни Недели"), перечисления были бы предпочтительны, потому что она показывает, что они сгруппированы; и, как Jason сказал, они безопасны с точки зрения типов. Если бы это - глобальная константа (как номер версии), это больше, для чего Вы использовали бы #define; хотя это - предмет большого количества дебатов.

1
ответ дан Smashery 26 November 2019 в 21:03
поделиться

Перечисления обычно предпочитаются по #define везде, где имеет смысл использовать перечисление:

  • Отладчики могут показать Вам символьное имя enum значение с (" openType: OpenExisting", а не" openType: 2",
  • Вы получаете немного больше защиты от столкновений имени, но это не настолько плохо, как это было (большинство компиляторов предупреждает о ре #define ition.

самое большое различие - то, что можно использовать перечисления в качестве типов:

// Yeah, dumb example
enum OpenType {
    OpenExisting,
    OpenOrCreate,
    Truncate
};

void OpenFile(const char* filename, OpenType openType, int bufferSize);

Это дает Вам проверку типа параметров (Вы не можете перепутать openType и bufferSize как легко), и облегчает находить то, что значения допустимы, делая Ваши интерфейсы намного легче использовать. Некоторые IDE могут даже дать Вам <забастовка> intellisense завершение кода!

5
ответ дан Simon Buchan 26 November 2019 в 21:03
поделиться

Определите команда препроцессора, она точно так же, как делает, "заменяют все" в Вашем редакторе, она может заменить строку другим и затем скомпилировать результат.

Перечисление является особым случаем типа, например, если Вы пишете:

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

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

Сводка: они - оба, но при использовании перечисления Вы получаете прибыль, проверка типа и при помощи определяет Вас, просто заменяют строки кода.

8
ответ дан Étienne 26 November 2019 в 21:03
поделиться

#define операторы обрабатываются препроцессором, прежде чем компилятор доберется для наблюдения кода, таким образом, это - в основном текстовая замена (это на самом деле немного более интеллектуально с использованием параметров и такого).

Перечисления являются частью самого языка C и имеют следующие преимущества.

1/у Них может быть тип, и компилятор может проверка типа их.

2/, Так как они доступны компилятору, информации о символе о них, может быть передан до отладчика, делая отладку легче.

17
ответ дан paxdiablo 26 November 2019 в 21:03
поделиться

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

Использование #define обычно не проблема, но поскольку у enum нет недостатков, я согласен с этим.

В C ++ я также обычно предпочитаю enum const int , хотя в C ++ a const int может использоваться вместо буквального целочисленного значения (в отличие от в C), потому что enum переносится на C (с которым я все еще много работаю).

2
ответ дан 26 November 2019 в 21:03
поделиться

Помимо всего уже написанного, одно сказано, но не показано, а вместо этого интересно. Например.

enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP };
//...
void do_action( enum action anAction, info_t x );

Рассмотрение действия как типа проясняет ситуацию. Используя define, вы должны написать

void do_action(int anAction, info_t x);
2
ответ дан 26 November 2019 в 21:03
поделиться

перечисления больше используются для перечисления некоторого набора, например, дней в неделе. Если вам нужно только одно постоянное число, const int (или double и т. Д.) Определенно будет лучше, чем enum. Мне лично не нравится #define (по крайней мере, не для определения некоторых констант), потому что он не дает мне безопасности типов, но вы, конечно, можете использовать его, если он вам больше подходит.

1
ответ дан 26 November 2019 в 21:03
поделиться

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

2
ответ дан 26 November 2019 в 21:03
поделиться

По возможности всегда лучше использовать перечисление. Использование перечисления дает компилятору больше информации о вашем исходном коде, определение препроцессора никогда не просматривается компилятором и, следовательно, несет меньше информации.

Для реализации, например, набор режимов, использование перечисления позволяет компилятору отлавливать, например, отсутствующие case -выражения в переключателе.

4
ответ дан 26 November 2019 в 21:03
поделиться

Создание перечисления создает не только литералы, но и тип, который группирует эти литералы: Это добавляет семантику в ваш код, которую компилятор может проверить.

Более того, при использовании отладчика вы имеете доступ к значениям литералов перечисления. В случае с #define это не всегда так.

1
ответ дан 26 November 2019 в 21:03
поделиться

#define - это команда препроцессора, enum - в языке C или C++.

Для таких случаев всегда лучше использовать enum, а не #define. Одно дело - безопасность типов. Другой - когда у вас есть последовательность значений, вам нужно указать в перечислении только начало последовательности, остальные значения получают последовательные значения.

enum {
  ONE = 1,
  TWO,
  THREE,
  FOUR
};

вместо

#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4

В качестве примечания, есть еще некоторые случаи, когда вы можете использовать #define (обычно для некоторых видов макросов, если вам нужно иметь возможность построить идентификатор, который содержит константу), но это своего рода черная магия макросов, и очень очень редко, чтобы быть способом пойти. Если вы идете на такие крайности, вам, вероятно, следует использовать шаблон C++ (но если вы застряли с C...).

3
ответ дан 26 November 2019 в 21:03
поделиться

enum может группировать несколько элементов в одну категорию:

enum fruits{ apple=1234, orange=12345};

в то время как #define может создавать только несвязанные константы:

#define apple 1234
#define orange 12345
3
ответ дан 26 November 2019 в 21:03
поделиться