Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 7 из 7
  1. #1
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±

    Конфликт переменных с enum

    Всем доброго времени суток!

    Возник вопрос, почему при использовании одинаковых названий, содержащихся в разных enum'ах ошибки нет, а при использовании переменной, название которой есть хотя бы в одном из них, вызывает предупреждение?
    1. enum MyEnum
    2. {
    3. foo,
    4. bar
    5. }
    6. enum AnotherEnum
    7. {
    8. foo,
    9. bar
    10. }
    11.  
    12. stock test()
    13. {
    14. new foo;
    15. }
    16. stock test2(foo)
    17. {
    18.  
    19. }


    Возникает warning 219: local variable "foo" shadows a variable at a preceding level

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

    Нет ли каких-то возможных вариантов решения? Порядком поднадоели повсеместные префиксы, и хочется использовать простые названия внутри enum'ов вроде ID, name и т.п., но в таком случае я теряю их во всех остальных местах.

    При этом в аргументах функции также нельзя использовать данное имя, однако, например, тот же name с native'ом GetPlayerName не конфликтует (вероятно, по той же причине, что и forward сам по себе не конфликтует, если не писать сам public)
    Последний раз редактировалось DCPSHER; 29.05.2018 в 01:58.

  2. #2
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от DCPSHER Посмотреть сообщение
    Всем доброго времени суток!

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

    Цитата Сообщение от DCPSHER Посмотреть сообщение
    При этом в аргументах функции также нельзя использовать данное имя, однако, например, тот же name с native'ом GetPlayerName не конфликтует
    Да, потому что нативные функции объявлены до перечислений.
    Также следует понимать разницу между глобальными идентификаторами (под "идентификаторами" имеются в виду названия функций, переменных, констант и пр.) и локальными. Аргументы функций являются локальными идентификаторами, существующими только в пределах функции, и поэтому если у двух разных функций есть аргументы с одинаковыми названиями, конфликта не будет. А вот глобальные переменные, константы и функции - это (сюрприз!) глобальные идентификаторы и им нужно задавать осмысленные названия, а не всякие "i", "j" или "string" (более подробно и с примерами эта тема рассмотрена в рекомендациях по написанию кода). И константы внутри перечислений (в том числе в именованных перечислениях) тоже глобальные, потому им обычно и задают префиксы.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  3. Пользователь сказал cпасибо:
    DCPSHER (31.05.2018)
  4. #3
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±
    Большое спасибо за ответ!

    Про локально-глобальные вещи я прекрасно понимаю, просто хотелось узнать именно про особенность enum'ов, и их отсутствия междоусобного конфликта, но рьяной атакой любой попытки использовать то, что использует хоть один из них. Если бы внутри были тоже конфликты, тогда в моих глазах это выглядело более логичным, конечно.

  5. #4
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Потому что для именованных перечислений (enum) действуют особые правила: константы внутри разных именованных перечислений не конфликтуют друг с другом.
    Стоп, разве не будет ошибок, если в этих перечислениях значения констант будут разными?

  6. #5
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от VVWVV Посмотреть сообщение
    Стоп, разве не будет ошибок, если в этих перечислениях значения констант будут разными?
    Ну вот взять, к примеру, такой код:
    1. const MAX_PLAYERS = 1000;
    2.  
    3. enum e_PlayerInfo
    4. {
    5. // Координаты игрока
    6. Float:pX,
    7. Float:pY,
    8. Float:pZ
    9. };
    10.  
    11. enum e_PickupInfo
    12. {
    13. // Координаты пикапа
    14. Float:pX,
    15. Float:pY,
    16. Float:pZ
    17. };
    18.  
    19. new player_info[MAX_PLAYERS][e_PlayerInfo];
    20. #pragma unused player_info
    21.  
    22. main()
    23. {
    24. player_info[0][pX] = 0.0;
    25. }

    "Player" и "Pickup" начинаются с одной буквы, поэтому префикс для констант в обоих перечислениях одинаковый - но код компилируется без единого варнинга. А всё потому, что компилятор знает, что в "player_info[0][pX] = 0.0;" под "pX" имеется в виду именно та константа, которая объявлена в перечислении "e_PlayerInfo", т.к. именно это перечисление указано в качестве меры в объявлении массива "new player_info[MAX_PLAYERS][e_PlayerInfo];". Опять же повторюсь, это "исключение" относится только к именованным enum'ам, для констант в анонимных перечислениях действуют те же правила, что и для констант, объявленных с помощью ключевого слова const.


    Цитата Сообщение от DCPSHER Посмотреть сообщение
    Если бы внутри были тоже конфликты, тогда в моих глазах это выглядело более логичным, конечно.
    Если запретить объявлять константы с одинаковыми именами внутри именованных перечислений, ничего хорошего из этого не выйдет. Взять тот же пример выше: придётся придумывать новый префикс для констант либо внутри "e_PlayerInfo", либо внутри "e_PickupInfo", а заодно и менять название enum'а для соответствия. Сплошные минусы, в то время как компилятор и без запретов может правильно разобраться в ситуации.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  7. 2 пользователя(ей) сказали cпасибо:
    DCPSHER (01.06.2018) Elrmrnt-Kritik (31.05.2018)
  8. #6
    Аватар для DCPSHER
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.05.2018
    Сообщений
    16
    Репутация:
    2 ±
    Если запретить объявлять константы с одинаковыми именами внутри именованных перечислений, ничего хорошего из этого не выйдет. Взять тот же пример выше: придётся придумывать новый префикс для констант либо внутри "e_PlayerInfo", либо внутри "e_PickupInfo", а заодно и менять название enum'а для соответствия. Сплошные минусы, в то время как компилятор и без запретов может правильно разобраться в ситуации.
    Это-то понятно, я тут наоборот с либеральными взглядами, и был бы рад наоборот отсутствию конфликтов переменных и enum'ов)

  9. #7
    Аватар для VVWVV
    ?

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Ну вот взять, к примеру, такой код:
    1. const MAX_PLAYERS = 1000;
    2.  
    3. enum e_PlayerInfo
    4. {
    5. // Координаты игрока
    6. Float:pX,
    7. Float:pY,
    8. Float:pZ
    9. };
    10.  
    11. enum e_PickupInfo
    12. {
    13. // Координаты пикапа
    14. Float:pX,
    15. Float:pY,
    16. Float:pZ
    17. };
    18.  
    19. new player_info[MAX_PLAYERS][e_PlayerInfo];
    20. #pragma unused player_info
    21.  
    22. main()
    23. {
    24. player_info[0][pX] = 0.0;
    25. }
    Я говорил об этом:
    1. enum a1 { a = 0 }; enum a2 { a = 1 };

    Насколько я помню, я натыкался на данную ошибку где-то год назад.

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •