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

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±

    Перегрузка операторов

    Всем привет!

    В этом уроке я расскажу о перегрузке операторов.

    Введение
    В Pawn, как и в языке C++, присутствует перегрузка операторов. Она используется для изменения возвращаемого значения при какой-либо операции. Таким образом, она делает код более компактным, ведь при ином случае необходимо использовать обычные функции.

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

    Ко всему прочему, имеет ряд ограничений. Например, вы не можете использовать оператор & для того, чтобы узнать адрес переменной. Кроме того, вы не можете использовать массивы/строки в аргументах. Хотя на этот счёт существует оператор emit, с помощью которого можно что-то сделать.

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

    Принцип работы
    Синтаксис перегрузки операторов очень прост: необходимо создать функцию, указать тег возвращаемого значения, а в самом названии указать ключевое слово operator и сам оператор. В круглых скобках необходимо указать заготовленные аргументы, иначе компилятор выдаст ошибку.

    Пример перегрузки оператора:
    PHP код:
    stock
        SomeTag
    :operator*(SomeTag:multiplicandsSomeTag:multiplier)
    {
        return 
    SomeTag:((multiplicands multiplier) + SomeTag:2);




    Однако, как говорилось выше, имеется ряд ограничений:
    1. Нельзя использовать оператор &, а также массивы в аргументах к оператору.
    2. Ограниченное число операторов. Таким образом, вы не сможете перегрузить большую часть операторов.
      Операторы не попавшие под ограничение:
      • Арифметические операторы ("=", "+" (сложение), "-" (вычитание), "+" (унарный плюс), "-" (унарный минус), "*", "/", "%", "++"(префиксный/постфиксный), "--" (префиксный/постфиксный)).
      • Операторы сравнения ("==", "!=", ">", "<", ">=", "<=").
      • Оператор логического НЕ ("!").


    Если говорить о составных операторах, то они работают так, как и перегруженные. Например, у нас есть перегруженный +, то оператор += будет работать так, как и оператор + и т.д.




    Для перегрузки оператора необходимо также знать его определение. Ниже приведена таблица с определениями операторов:
     Определения операторов
    Оператор Определение
    Присваивание
    PHP код:
    SomeTag:operator=(SomeTag:a
    Сложение
    PHP код:
    SomeTag:operator+(SomeTag:aSomeTag:b
    Вычитание
    PHP код:
    SomeTag:operator-(SomeTag:aSomeTag:b
    Унарный плюс
    PHP код:
    SomeTag:operator+(SomeTag:a
    Унарный минус
    PHP код:
    SomeTag:operator-(SomeTag:a
    Умножение
    PHP код:
    SomeTag:operator*(SomeTag:aSomeTag:b
    Деление
    PHP код:
    SomeTag:operator/(SomeTag:aSomeTag:b
    Остаток от деления
    PHP код:
    SomeTag:operator%(SomeTag:aSomeTag:b
    Инкремент (префиксный/постфиксный)
    PHP код:
    SomeTag:operator++(SomeTag:a
    Декремент (префиксный/постфиксный)
    PHP код:
    SomeTag:operator--(SomeTag:a
    Равенство
    PHP код:
    bool:operator==(SomeTag:aSomeTag:b
    Неравенство
    PHP код:
    bool:operator!=(SomeTag:aSomeTag:b
    Больше
    PHP код:
    bool:operator>(SomeTag:aSomeTag:b
    Меньше
    PHP код:
    bool:operator<(SomeTag:aSomeTag:b
    Больше или равно
    PHP код:
    bool:operator>=(SomeTag:aSomeTag:b
    Меньше или равно
    PHP код:
    bool:operator<=(SomeTag:aSomeTag:b
    Логическое отрицание, НЕ
    PHP код:
    bool:operator!(SomeTag:a





    Следует помнить, что для каждого тега необходимо использовать свою функцию. Таким образом, у вас не получится сделать так:
    PHP код:
    stock // Ошибочный код
        
    SomeTag:operator+(SomeTag:a, {Float,bool}:b)
    {
        return 
    SomeTag:(_:_:b);

    Для этого необходимо создать две функции:
    PHP код:
    stock
        SomeTag
    :operator+(SomeTag:aFloat:b)
    {
        return 
    SomeTag:(_:_:b);
    }

    stock
        SomeTag
    :operator+(SomeTag:abool:b)
    {
        return 
    SomeTag:(_:_:b);


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

    Читал комментарии некоторых пользователей, где они говорил, что выражение с перегруженным оператором быстрее, чем вызов нативной функции. Поэтому я решил аргументировать свой ответ. Приведу ассемблерный листинг (с использованием оператора):
     Aссемблерный листинг

    PHP код:
        proc    operator+(Float:,_:)
        ; 
    line 79
        
    break    ; c
        
    ;$lcl oper2 10
        
    ;$lcl oper1 c
        
    line 79
        
    break    ; 10
        load
    .s.pri 10
        push
    .pri
        
    ;$par
        push
    .c 4
        sysreq
    .c 0    float
        stack 8
        push
    .pri
        
    ;$par
        load
    .s.pri c
        push
    .pri
        
    ;$par
        push
    .c 8
        sysreq
    .c 1    floatadd
        stack c
        retn

        proc    
    main
        
    line 6
        
    break    ; 68
        
    line 7
        
    break    ; 6c
        
    ;$lcl a fffffffc
        stack fffffffc
        zero
    .pri
        stor
    .s.pri fffffffc
        
    ;$exp
        
    line 8
        
    break    ; 84
        load
    .s.pri fffffffc
        
    const.alt 7
        push
    .alt
        push
    .pri
        
    ;$par
        push
    .c 8
        call .40000004
    +0    operator+(Float:,_:)
        
    stor.s.pri fffffffc
        
    ;$exp
        stack 4
        zero
    .pri
        retn 


    Если же говорить лишь об использовании нативной функции, то вот листинг:
     Aссемблерный листинг

    PHP код:
        proc    main
        
    line 6
        
    break    ; c
        
    line 7
        
    break    ; 10
        
    ;$lcl a fffffffc
        stack fffffffc
        zero
    .pri
        stor
    .s.pri fffffffc
        
    ;$exp
        
    line 8
        
    break    ; 28
        
    const.pri 40e00000
        push
    .pri
        
    ;$par
        load
    .s.pri fffffffc
        push
    .pri
        
    ;$par
        push
    .c 8
        sysreq
    .c 0    floatadd
        stack c
        stor
    .s.pri fffffffc
        
    ;$exp
        stack 4
        zero
    .pri
        retn 


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

    Вывод
    В Pawn перегрузка операторов является очень закрытой. Как уже было сказано выше: многие операторы нельзя перегрузить. Кроме того, очень много ограничений в аргументах функции-перегрузки: нельзя использовать массивы, нельзя использовать оператор & для получения адреса и т.п.

    Автор: VVWVV

    Копирование данной статьи на других ресурсах без разрешения автора запрещено!
    Последний раз редактировалось VVWVV; 06.08.2018 в 11:23.

  2. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от VVWVV Посмотреть сообщение
    она делает код более меньше
    "более компактным" звучало бы лучше =)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

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

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    "более компактным" звучало бы лучше =)
    Да. Исправил.

  4. #4
    Аватар для KrutoyKrosch
    Пользователь

    Статус
    Оффлайн
    Регистрация
    26.02.2016
    Сообщений
    301
    Репутация:
    7 ±


    Зачем такая эксклюзивность?

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

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от KrutoyKrosch Посмотреть сообщение


    Зачем такая эксклюзивность?
    Для развития данного форума. Например, для привлечения новых посетителей и т.п.

  6. #6
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    В реальных условиях ползи от перегрузки в Pawn - мало. Например: оператор "==" не перегрузить для проверки строк (используя strcmp), т.к никак не передашь в функцию массив. Очень урезанная перегрузка. Технического применения ее почти нет.

    И кстати в Cях нельзя же перегрузить операторы.
    Последний раз редактировалось $continue$; 03.01.2017 в 21:56.
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

  7. #7
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    И кстати в Cях нельзя же перегрузить операторы.
    Там оно и не нужно. А в Pawn они есть исключительно из-за отсутствия типов и необходимости поддержки Float чисел.

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

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    В реальных условиях ползи от перегрузки в Pawn - мало. Например: оператор "==" не перегрузить для проверки строк (используя strcmp), т.к никак не передашь в функцию массив. Очень урезанная перегрузка. Технического применения ее почти нет.

    И кстати в Cях нельзя же перегрузить операторы.
    В исходниках Pawn частично реализована "привязка" к строковой библиотеке BString. И, я так понимаю, единственное, что удерживает её от попадания в релиз - условия лицензии (двойное лицензирование под GPL и 3-пунктовой BSDL), накладывающие дополнительные ограничения на релиз в объектной форме. Тем не менее, можно доработать это поделие до плагина к SA-MP.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  9. #9
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    Я к тому, что у автора в шапке темы "C/C++"
    Цитата Сообщение от ziggi Посмотреть сообщение
    Там оно и не нужно. А в Pawn они есть исключительно из-за отсутствия типов и необходимости поддержки Float чисел.
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

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

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    731
    Репутация:
    353 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    В реальных условиях ползи от перегрузки в Pawn - мало. Например: оператор "==" не перегрузить для проверки строк (используя strcmp), т.к никак не передашь в функцию массив. Очень урезанная перегрузка. Технического применения ее почти нет.

    И кстати в Cях нельзя же перегрузить операторы.
    Да. Исправил.

 

 

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

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

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

Ваши права

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