Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: переопределение оператора []  (Прочитано 6309 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Serguntii
Помогающий

ru
Offline Offline

« : 05-12-2013 10:37 » 

Разбираюсь с исходником ftp://ftp.graco.unb.br/jatlite/alvares/retrofitting/linuxcnc.org/handbook/fileref/rcslib/posemath_8h-source.html не совсем понимаю как работает этот код помогите понять.
Код:
struct PM_CARTESIAN
{
 
   PM_CARTESIAN() {};                                                  // это конструктор ничего не получает
   PM_CARTESIAN(double _x, double _y, double _z);   // этот конструктор  получает double _x, double _y, double _z)
   
 #ifdef INCLUDE_POSEMATH_COPY_CONSTRUCTORS
   PM_CARTESIAN(PM_CCONST PM_CARTESIAN &cart); // added  7-May-1997 by WPS
 #endif
 
   PM_CARTESIAN(PM_CONST PM_CYLINDRICAL PM_REF c);  // этот конструктор  получает структуру PM_CYLINDRICAL  )
   PM_CARTESIAN(PM_CONST PM_SPHERICAL PM_REF s);     // этот конструктор  получает структуру PM_SPHERICAL  )
 
// весь код который выше ничего не меняет просто получает или нет при вызове конструктора аргументы, правильно?


   //здесь переопределение оператора [] ()  не совсем понимаю как это работает, заменяется оператор [] и () в коде есть новые определение операторов, объясните простыми словами как это работает?
   double & operator [] (int n);             /* this[n] */
   PM_CARTESIAN operator = (PM_CARTESIAN v); /* this = v */
 
   /* data */
   double x, y, z;                     /* this.x, etc. */
 };

Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 05-12-2013 10:59 » 

1. Что есть оператор []?
2. Что есть оператор ()?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Serguntii
Помогающий

ru
Offline Offline

« Ответ #2 : 05-12-2013 11:08 » 

элемент массива [] и вызов функции () .
операторы переопределены так:
Код:
/* compare operators */
 extern int operator == (PM_CARTESIAN v1, PM_CARTESIAN v2);
 extern int operator == (PM_QUATERNION q1, PM_QUATERNION q2);
 extern int operator == (PM_POSE p1, PM_POSE p2);
 extern int operator != (PM_CARTESIAN v1, PM_CARTESIAN v2);
 extern int operator != (PM_QUATERNION q1, PM_QUATERNION q2);
 extern int operator != (PM_POSE p1, PM_POSE p2);
 
 /* translation +, -, scalar *, - */
 
 /* v + v */
 extern PM_CARTESIAN operator + (PM_CARTESIAN v1, PM_CARTESIAN v2);
 /* v - v */
 extern PM_CARTESIAN operator - (PM_CARTESIAN v1, PM_CARTESIAN v2);
/* v * s */
 extern PM_CARTESIAN operator * (PM_CARTESIAN v, double s);
 /* s * v */
 extern PM_CARTESIAN operator * (double s, PM_CARTESIAN v);
 /* v / s */
 extern PM_CARTESIAN operator / (PM_CARTESIAN v, double s);
 
 /* rotation * by scalar, translation, and rotation */
 
 /* s * q */
 extern PM_QUATERNION operator * (double s, PM_QUATERNION q);
 /* q * s */
 extern PM_QUATERNION operator * ( PM_QUATERNION q, double s);
 /* q / s */
 extern PM_QUATERNION operator / ( PM_QUATERNION q, double s);
 /* q * v */
 extern PM_CARTESIAN operator * (PM_QUATERNION q, PM_CARTESIAN v);
 /* q * q */
 extern PM_QUATERNION operator * (PM_QUATERNION q1, PM_QUATERNION q2);
 /* m * m */
 extern PM_ROTATION_MATRIX operator * (PM_ROTATION_MATRIX m1, PM_ROTATION_MATRIX m2);
 
 /* pose operators */
 
Какой из них будет выполнен и при каких условиях? ни разу не приходилось пользоваться такой конструкцией.
например в коде объявляю
Код:
PM_CARTESIAN mystr;
mystr.operator ???

 



« Последнее редактирование: 05-12-2013 11:12 от sergeyan » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 05-12-2013 12:07 » 

элемент массива [] и вызов функции () .

[] - правильно, те при передачи индекса будет возвращён элемент массива с этим индексом.

() - неправильно, что значит оператор вызова ф-ции? Как ты себе это представляешь?

Цитата
операторы переопределены так:

А это к чему? Ведь ни [] ни () в этом списке нет. Зачем ты вываливаешь кучу какого-то кода? Или ты в приниципе не понимаешь как работает переопределение чего-либо, операторов в частности?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Serguntii
Помогающий

ru
Offline Offline

« Ответ #4 : 05-12-2013 12:25 » 

Вот в этом случае не совсем понимаю. (
Функция расположена в адресном пространстве, при ее вызове в счетчик команд записывается ее адрес по которому она находиться..
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 05-12-2013 13:10 » 

sergeyan, оператор - это, с одной стороны, синтаксическая конструкция языка, с другой стороны, она должна что-то делать. Вот что она делает - определяется функцией вида operator. Ты наверняка [] в программе пользовался - ну и пользуйся дальше, но при этом для соответствующего типа переменных будет вызываться соответствующая функция.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 06-12-2013 15:40 » 

Нда... как всё запущено. Срочно учи теорию. () - это не вызов ф-ции, а оператор приведения типа (агл. cast operator). Тебе случалось встречать такую конструкцию?

int i=3;
double d1 = (double)i;

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

Допустим у тебя есть некий класс:

Код: (C++)
class CClass123
{
public:
        CClass123(CString stData, double dData)
        {
                m_stData = stData;
                m_dData = dData;
        }

private:

        CString m_stData;
        double m_dData;
};

есть пара ф-ций для отображения неких данных:

Код: (C++)
void PrintStringData(CString data)
{
        _tprintf(L"String data: %s\r\n", data);
}

void PrintDoubleData(double data)
{
        _tprintf(L"Double data: %f\r\n", data);
}

ты хочешь вызвать эти ф-ции с твоим объектом:

Код: (C++)
...
        CClass123 a(_T("Hello"), 6.789);
        PrintStringData(a);
        PrintDoubleData(a);

Получится? А почему?
(не спеши подглядывать, попробуй сам ответить)
Потому что ф-ции требуют строку или вещественный тип. Нет ф-ции с параметром CClass123.
В этом случае нам поможет переопределение оператора типа:

Код: (C++)
class CClass123
{
public:
        CClass123(CString stData, double dData)
        {
                m_stData = stData;
                m_dData = dData;
        }

        operator CString ()
        {
                return m_stData;
        }

        operator double()
        {
                return m_dData;
        }

private:

        CString m_stData;
        double m_dData;
};

Теперь всё в порядке. Можно вызывать ф-ции с объектом CClass123.


Но это всё "Несправедливо. Зачем открывать тайны сложного, если необъяснимо простое?" (с)

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

Код: (C++)
class CFractionalNumber
{
public:

        CFractionalNumber()
        {
                m_nNumerator = 0;
                m_nDenominator = 1;
        }

        CFractionalNumber(int nNumerator, int nDenominator)
        {
                m_nNumerator = nNumerator;
                m_nDenominator = nDenominator;
        }

private:
        int m_nNumerator;
        int m_nDenominator;
};

Необходимо выполнить след операции с объектами этого типа:

Код: (C++)
        CFractionalNumber fc1(3, 4);   // 3/4
        CFractionalNumber fc2(2, 5);   // 2/5

        CFractionalNumber fcResult = fc1 + fc2;

        fcResult = fc1 - fc2;
        fcResult = fc1 - 3;

        fcResult = fc1 * fc2;
        fcResult = fc1 * 5;

        fcResult = fc1 / fc2;
        fcResult = fc1 / 4;

        fcResult += 3;
        fcResult *= CFractionalNumber(12, 13);
 
« Последнее редактирование: 06-12-2013 15:42 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 08-12-2013 10:25 » 

Джон, справедливости ради, есть оператор приведения типа с синтаксисом operator Type () (arg) и оператор вызова функции Type operator()(args) - который используется в функторах  в духе
Код: (C++)
class SomeFunctor {
    public:
      double operator() (double arg1, double arg2) { /*возвращает значение некоторой функции 2х аргументов*/ }
};

int main() {
  SomeFunctor func;
  double v = func(2.72, 3.14);
  return 0;
}
Впрочем, у автора в исходном топике не нашёл ни того, ни другого: там оператор присваивания объявлен после индексного оператора.

Вообще, если я правильно понял, sergeyan смущает количество скобок в объявлении operator[](int n), как и нотация описания операторов в целом.
Так вот, sergeyan, то, что у операторов стоит до списка аргументов, следует считать частью имени объявляемой функции, просто имя такое, специфическое, особый случай в языке: пишется bool operator == (SomeType left, SomeType right), вызов его в коде выглядит просто как ==, в случае же operator[](int index) в коде будет object[index], а для SomeType operator()(args) - аналог вызова функции: object(args).
В принципе, можно вызвать оператор и по его полному имени, например, object.operator[](index), но это очень редко бывает нужно (и скорее всего, чтобы передать указатель на этот метод куда-нибудь, а не просто вызвать этот метод)

Для чего всё это сделано? Прежде всего, думаю, для того, чтобы компилятор и программист могли спокойно отличать конструкции, описывающие операторы, от всех прочих: ведь если убрать ключевое слово operator, может получиться что-то двусмысленное, сложно отличимое от простой опечатки.
« Последнее редактирование: 08-12-2013 10:50 от Вад » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 08-12-2013 14:08 » new

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines