Форум программистов, компьютерный форум CyberForum.ru

Вывод данных и перегрузка операторов. - C++

Восстановить пароль Регистрация
 
Грымзик
 Аватар для Грымзик
2466 / 1443 / 31
Регистрация: 14.09.2009
Сообщений: 2,742
07.04.2012, 00:08     Вывод данных и перегрузка операторов. #1
Добрый вечер, объясните пожалуйста что я не так делаю.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
class A{
public:
       int a;
       A& operator++(){         
          ++a;
          return *this;
       }
};
 
int main(void) {
    A elem={1};
    cout<<elem.a<<(++elem).a<<(++elem).a<<elem.a;
    //system("PAUSE");
    return 0;
}
Выводиться 3333. Почему не 1233? И почему если я сделаю так
C++ (Qt)
1
2
cout<<elem.a;
cout<<(++elem).a<<(++elem).a<<elem.a;
то уже будет 1333?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.04.2012, 00:08     Вывод данных и перегрузка операторов.
Посмотрите здесь:

Перегрузка операторов в С++ C++
Перегрузка операторов C++
Перегрузка операторов C++
перегрузка операторов C++
Перегрузка операторов с++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
07.04.2012, 00:18     Вывод данных и перегрузка операторов. #2
Какова цель? Я если честно вообще не могу понять половины из написанного кода
Грымзик
 Аватар для Грымзик
2466 / 1443 / 31
Регистрация: 14.09.2009
Сообщений: 2,742
07.04.2012, 00:21  [ТС]     Вывод данных и перегрузка операторов. #3
Цель - изучение языка, это я попробовала поперезагружать операторы.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
07.04.2012, 00:24     Вывод данных и перегрузка операторов. #4
Ну тогда думаю имелось ввиду вот это
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
 
class A {
public:
  A( int b ) : a( b ) {
 
  };
       int a;
       A& operator++(){
          ++a;
          return *this;
       }
};
 
int main(void) {
    A elem(1);
 
    cout << elem.a;
 
    ++elem;
    cout << elem.a;
 
    ++elem;
    cout << elem.a;
    //system("PAUSE");
    return 0;
}
Грымзик
 Аватар для Грымзик
2466 / 1443 / 31
Регистрация: 14.09.2009
Сообщений: 2,742
07.04.2012, 00:28  [ТС]     Вывод данных и перегрузка операторов. #5
Спасибо, но Вы не совсем меня поняли. Меня интересует не как заствить работать, а почему не работает вот так
cout<<elem.a<<(++elem).a<<(++elem).a<<elem.a;
И что меняется при разделении на несколько cout.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
07.04.2012, 00:35     Вывод данных и перегрузка операторов. #6
На сколько знаю, очередность операций в потоке cout не определена, и зависит от компилятора. У меня например выводит 3321. Поэтому, думаю, вычисления лучше производить отдельным оператором, а потом уже выводить данные.
Грымзик
 Аватар для Грымзик
2466 / 1443 / 31
Регистрация: 14.09.2009
Сообщений: 2,742
07.04.2012, 00:49  [ТС]     Вывод данных и перегрузка операторов. #7
Ну вот например же при
C++ (Qt)
1
2
int a=1;
cout<<a<<++a<<++a<<a;
будет выведено 1233, всегда. Никогда не слышала про неопределенность очередности вывода. Может тут как-то с буфером связано?
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
07.04.2012, 01:00     Вывод данных и перегрузка операторов. #8
Цитата Сообщение от Грымзик Посмотреть сообщение
Может тут как-то с буфером связано?
Скорее с реализацией отдельного компилятора

Добавлено через 6 минут
Я же с вашим кодом получаю
main.cpp:19:33: error: operation on 'a' may be undefined [-Werror=sequence-point]
То есть компилятор говорит что операция над a может быть не определена. Так как переменная модифицируется два раза в потоке. Вот думаю будет интересно почитать тык
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
07.04.2012, 01:36     Вывод данных и перегрузка операторов. #9
Toshkarik, дело не в потоке, поток - просто абстракция, неизвестная компилятору. Дело в точках следования, по сути, такое выражении можно сравнить с
C++
1
i = i++ + ++i;
Это очень любят давать на собеседованиях.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
07.04.2012, 02:40     Вывод данных и перегрузка операторов. #10
silent_1991, да, я это понимаю. Я просто говорил про данный конкретный случай. На сколько я понимаю, переменная должна модифицироваться ровно один раз в промежутке от одной точки следования до другой. В данном случае от одной ; до другой ;
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
07.04.2012, 03:08     Вывод данных и перегрузка операторов. #11
Цитата Сообщение от Toshkarik Посмотреть сообщение
переменная должна модифицироваться ровно один раз в промежутке от одной точки следования до другой
Не должна. Просто переход через точку следования гарантирует, что все эффекты от действий, произведённых до этой точки следования, уже вступили в силу. Проблема здесь в том, что стандарт не определяет, как должен вычисляться инкремент (а значит, что когда он реально вычислится, зависит от самых разных вещей, начиная с внутреннего представления программы в компиляторе и заканчивая вспышками на солнце).
В данном конкретном случае могу предположить, что компилятор воспринял выражение
C++
1
cout<<elem.a<<(++elem).a<<(++elem).a<<elem.a;
как
C++
1
2
3
4
5
6
7
8
//(++elem).a;
t2 = elem.operator++().operator++().a;
// Скорее всего, в данном случае точкой следования является не очередной
// каскадный вызов operator<<, а ; в конце всего выражения; таким образом,
// компилятор вправе вычислять аргументы как ему вздумается, и он просто
// вычислил всё один раз и сохранил во временной переменной (возможно, свою
// роль сыграл и оптимизатор)
cout.operator<<(t2).operator<<(t2).operator<<(t2).operator<<(t2);
отчего и наблюдается данный эффект.

Добавлено через 12 минут
Я ошибся. На самом деле код будет воспринят как
C++
1
operator<<(operator<<(operator<<(operator<<(cout, elem.a), elem.operator++().a), elem.operator++().a), elem.a);
и тогда всё встаёт на свои места, порядок вычисления аргументов при вызове функции не определён стандартом, известно лишь, что к моменту вызова все побочный эффекты вступят в силу (т.е. момент вызова функции после вычисления всех аргументов - точка следования). Вот мы и получаем неопределённый порядок вычисления аргументов.
Грымзик
 Аватар для Грымзик
2466 / 1443 / 31
Регистрация: 14.09.2009
Сообщений: 2,742
07.04.2012, 21:57  [ТС]     Вывод данных и перегрузка операторов. #12
Спасибо большое! Но все-таки поражаюсь, ведь для ++i код будет воспринят также. Почему тогда уже другой порядок вычисления аргументов Теперь буду остерегаться делать то, что раньше для меня было абсолютно естественным.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.04.2012, 23:17     Вывод данных и перегрузка операторов.
Еще ссылки по теме:

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

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
07.04.2012, 23:17     Вывод данных и перегрузка операторов. #13
Грымзик, в одном случае вызов пользовательского метода (operator++), в другом - выполнение стандартной операции. Эти две вещи обрабатываются по-разному (пользовательские операции обрабатываются как функции).
Yandex
Объявления
07.04.2012, 23:17     Вывод данных и перегрузка операторов.
Ответ Создать тему
Опции темы

Текущее время: 13:36. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru