Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегрузка унарных операторов, Чем определяется приоритет? 
:(
    Опции темы
Чoо
Дата 9.12.2010, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



Подскажите пожалуйста. Вот код:
Код

/*
    Перегрузка унарных операторов
 */
#include <iostream>
using namespace std;

class complex{
    int real,imag;
public:
    complex(int re, int im):real(re),imag(im) {};

    //изменяет существующий объект
    complex& operator -()
    {
        real = -real;
        imag = -imag;
        return *this;
    }

    //создает объект, не изменяя существующий
    complex operator -() const
    {
        return complex(-real,-imag);
    }

    ~complex() {};
};

int main()
{
    complex c(10,20), d(0,0);
    -c;
    d = -c;
    return 0;
}


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


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
asmdzen
Дата 9.12.2010, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 28.11.2010

Репутация: 3
Всего: 5



Оказалось что компилятору всеравно что именно делает оператор, он просто вызывает const операторы только для const обьектов, чтоб принудительно его вызвать следует писать как-то так:
Код

int main()
{
    complex c(10,20), d(0,0);
    -c;
    d = -((const complex)c);
    return 0;
}


"c" изменится только один раз.
PM MAIL   Вверх
Чoо
Дата 9.12.2010, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



asmdzen,  переделал маин:
Код

int main()
{
    const complex c(10,20);
    complex d(0,0);
    d = -c;
    return 0;
}

теперь все понял. Спасибо за объяснение.

Вопрос решен.

Добавлено @ 22:49
asmdzen, ну в смысле по вашему пример следовал smile. Вызвал функцию для константного объекта smile

Это сообщение отредактировал(а) Чoо - 9.12.2010, 22:51


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Чoо
Дата 10.12.2010, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



рано пометил тему решенной smile.
вот простой код:
Код

/*
    Перегрузка унарной операции инкремента
 */
#include <iostream>
using namespace std;

class complex{
    int real,imag;
public:
    complex(int re, int im):real(re),imag(im) {};

    complex(const complex &p)
    {
        real = p.real;
        imag = p.imag;
    }

    //понадобятся для вывода экземпляра классa в поток
    friend ostream& operator << (ostream &strm, complex c);
    // ++c
    complex& operator ++ ()
    {
        ++real;
        ++imag;
        return *this;
    }

    //c++
    complex operator ++(int) //int - фиктивный параметр, что бы отличить постфикс, от префикса
    {
        complex old = *this; //будет вызван конструктор копирвания;
        ++*this;
        return old; //вернули объект до инкремента.
    }

    ~complex() {};
};

ostream& operator << (ostream &strm, complex c)
{
    return (strm << "real: " << c.real << "; imag: " << c.imag);
}


int main()
{
    complex c(10,20), d(25,30);
    cout << ++c << endl; //вернет 11, 21
    cout << d++; //вернет 25,30


    return 0;
}

хочу в функцию-оператор << передавать ссылку на объект, а не передавать объект по значению.  
если объявить:
Код

ostream& operator << (ostream &strm, complex &c)

то можно вызвать только:
Код

 cout << ++c;

ну оно понятно почему работает
а
Код

cout << c++;

нелльзя. Тоже понятно почему: возвращается объект, который копируется в исходный и уничтожается.

так вот, как мне все-таки и там и там передавать указатели на объекты?

Добавлено @ 13:49
возвращать ссылку в постфиксе(так):
Код

complex& operator ++(int)

не хочется, так как хочу скопировать поведение:
Код

int i=0,j=0;
cout << ++i;
cout << j++;


Это сообщение отредактировал(а) Чoо - 10.12.2010, 13:49


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
bsa
Дата 10.12.2010, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Всегда используй константные ссылки, если нет задачи менять объект внутри функции:
Код
ostream& operator << (ostream &strm, const complex &c)

Кстати, использование using namespace внутри хидеров причина очень больших неприятностей. Имей это в виду.

Добавлено через 2 минуты и 31 секунду
Цитата(Чoо @  9.12.2010,  22:43 Найти цитируемый пост)
    complex& operator -()
    {
        real = -real;
        imag = -imag;
        return *this;
    }
Делать подобные вещи - дурной тон. За редким исключением, изменение СТАНДАРТНОГО ПОВЕДЕНИЯ операторов и функций следует избегать, дабы не усложнять дальнейшее использование данного класса.
PM   Вверх
Чoо
Дата 10.12.2010, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



bsa, спасибо за помощь. всё пошло, хотя мне не понятно, почему ссылка, которая указывает на константный объект нормально воспринимается, а если просто ссылка - то это приводит к ошибке.

Цитата(bsa @  10.12.2010,  13:57 Найти цитируемый пост)
Всегда используй константные ссылки, если нет задачи менять объект внутри функции:

оК, учту это. в принципе это понятно.


Цитата(bsa @  10.12.2010,  13:57 Найти цитируемый пост)
Кстати, использование using namespace внутри хидеров причина очень больших неприятностей. Имей это в виду.

что такое хидеры?smile и почему могут быть неприятности? (есть где почитать?)

Цитата(bsa @  10.12.2010,  13:57 Найти цитируемый пост)
Делать подобные вещи - дурной тон. За редким исключением, изменение СТАНДАРТНОГО ПОВЕДЕНИЯ операторов...

тоже понял smile. Учту smile.


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Crafty
Дата 10.12.2010, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Цитата(Чoо @  10.12.2010,  19:09 Найти цитируемый пост)
что такое хидеры?
 файлы заголовка(header files) *.h.

Цитата(Чoо @  10.12.2010,  19:09 Найти цитируемый пост)
и почему могут быть неприятности? (есть где почитать?)

http://forum.vingrad.ru/index.php?showtopi...t&p=1964426

Это сообщение отредактировал(а) Crafty - 10.12.2010, 21:26
PM MAIL   Вверх
Чoо
Дата 10.12.2010, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



Crafty, 
Цитата(Crafty @  10.12.2010,  21:24 Найти цитируемый пост)
файлы заголовка(header files) *.h.

понял. подумал, сначала, что образовано от hide smile

прочитал, спасибо. 
тогда получается, что надо было писать так, вместо неймспейса?
Код

#include <iostream>
using std::cout;
using std::endl;
using std::ostream;





--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Crafty
Дата 10.12.2010, 22:56 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Желательно выработать у себя такую привычку не использовать using namespace, единственное исключение ИМХО в простых тестовых программках где один файл main.cpp.
Если в хидерах часто используется какое-то имя, то можно написать using std::cin, а если имя используется всего пару раз, то лучше обойтись вообще без using и писать явно из какого пространства это имя (например std::cout << "Hello world" << std::endl).

Это сообщение отредактировал(а) Crafty - 10.12.2010, 22:58
PM MAIL   Вверх
Чoо
Дата 10.12.2010, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



Crafty, по этой теме я вообще ни чего не знал, видать проблем не было smile. оК, буду исправляться smile. 
Вопрос пока помечу решенным, пока вопросов нет smile. 


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
Crafty
Дата 11.12.2010, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 319
Регистрация: 3.11.2008

Репутация: 12
Всего: 14



Цитата(Чoо @  10.12.2010,  23:45 Найти цитируемый пост)
видать проблем не было

Проблемы обычно возникают, когда в проекте используются несколько библиотек, и шанс совпадения имён значительно увеличивается.
PM MAIL   Вверх
Чoо
Дата 11.12.2010, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



снова вопрос. и снова по перегрузке унарных операторов.
Снвоа простой код:
Код

/*
    Перегрузка оператора косвенного выбора ->.
    "Умные" указатели"
 */
#include <iostream>

struct Y{
    int m;
};

class ptr{
    Y *p;
public:
    ptr(Y *o){
        p = o;
    }

    Y* operator ->()
    {
        //отсылка "донесения"
        std::cout << p->m << std::endl;
        return p;
    }
};


int main()
{
    ptr x(new Y);
    x->m = -1;
    x->m = 1;

    return 0;
}


буду рассматривать строку
Код

    x->m = -1;

Какова последовательность действий?:
1. вызов перегруженной функции оператора, которая выводит содержимое поля объекта в стандартный поток
2. передача указателя обратно в функцию main.
3. операция косвенного выбора -> (на этот раз неперегруженная) m
4. присвоение значения для поля m.

Я правильно понял? Посмотрел отладчиком, вроде так и получается. 


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
bsa
Дата 12.12.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Чoо, для умного указателя, у тебя не хватает деструктора.
Цитата(Crafty @  10.12.2010,  23:56 Найти цитируемый пост)
Если в хидерах часто используется какое-то имя, то можно написать using std::cin, а если имя используется всего пару раз, то лучше обойтись вообще без using и писать явно из какого пространства это имя (например std::cout << "Hello world" << std::endl).
В хидерах вообще никаких using (касательно каких-либо namespace) использовать не стоит, за исключением тела функций и собственных пространств имен. Потому что пользователь хидера может не ожидать, что ты ему в глобальное пространство вывалил что-то из другого.
PM   Вверх
Чoо
Дата 12.12.2010, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: 4
Всего: 4



Цитата(bsa @  12.12.2010,  12:12 Найти цитируемый пост)
для умного указателя, у тебя не хватает деструктора.

да, точно, забыл. 
Добавил в класс:
Код

~ptr() { delete p; }

а последовательность я правильно понял?


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
bsa
Дата 12.12.2010, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Чoо @  12.12.2010,  15:28 Найти цитируемый пост)
а последовательность я правильно понял? 
да
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0727 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.