Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > перегрузка оператора <<


Автор: versus 26.5.2005, 17:57
имеется вот такая простая программа

Код

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

class test
{
    int x;

public:
    test(int my_x): x(my_x) {}

    friend ostream& operator<<(ostream& stream, const test& obj);
};

ostream& operator<<(ostream& stream, const test& rhs)
{
    stream << rhs.x << endl;

//    return stream;
}

int main()
{
    test t(10);

    cout << t << endl;
    cout << endl << t;

    return 0;
}


Говорят, что в 20-ой строчке нужно обязательно возвращать ссылку на поток, чтобы operator<< можно было использовать в сложных (составных) выражениях. Действительно этот код, с закоментированной 20-ой строчкой с -Wall компилироваться отказывается по понятным причинам. Однако без -Wall поведение программы что с 20-ой строчкой, что без нее -- одинаковое.

Но если я не верну ссылку на поток в перегруженной функции, то куда тогда отправится endl в 27 строчке?

Автор: Mayk 26.5.2005, 18:43
Что значит куда? Туда, куда ему укажут. Функции operator<< возвращает значение допустим в EAX(что справедливо для 32 битных машин аля ix86). Соответственно туда он и отправит. Теперь попрубуем определить, чему он равняется. Разумеется он undefined в общем случае, но нас волнуют частности. В твоей функции есть лишь одна строка:

stream << rhs.x << endl;

Как думаешь, чему равняется eax после ее выполнения? Правильно, eax равен stream'у, т.к. stream<<endl возвращает значение. А так как больше твоя функция больше ничего не делает, то eax не меняется и потому эта функция возвращает stream.
Надеюсь понятно объяснил

Хотя в любом случае, это не оправдание чтобы забивать на return stream;


Автор: versus 26.5.2005, 19:22
Ага, понятно.

После того как убрал из функции

stream << rhs.x << endl;

программка как и следовало ожидать свалилась в сегфолт.

спасибо.

Автор: yours-tester 31.5.2005, 18:13
Дополнительный вопрос к теме.
Если в этой програмке заменить несколько первых строчек вот так:

Код

#include <iostream>
using namespace std;

//using std::ostream;
//using std::cout;
//using std::endl;


то она перестаёт компилироваться, а по моему должна.
Не пойму почему? Может кто подскажет?
--------------------Configuration: Test - Win32 Debug--------------------
Compiling...
test-1.cpp
D:\docs\Work\VC++\Test\test-1.cpp(20) : error C2248: 'x' : cannot access private member declared in class 'test'
D:\docs\Work\VC++\Test\test-1.cpp(10) : see declaration of 'x'
D:\docs\Work\VC++\Test\test-1.cpp(29) : error C2593: 'operator <<' is ambiguous
D:\docs\Work\VC++\Test\test-1.cpp(30) : error C2593: 'operator <<' is ambiguous
Error executing cl.exe.

test-1.obj - 3 error(s), 0 warning(s)[code=cpp]




Автор: versus 31.5.2005, 18:32
без пол-литр... тьфу-ты, без сурса test-1.cpp тут не разобраться...

>Если в этой програмке заменить несколько первых строчек вот так:
Очевидно в программке что-то изменили кроме первых строчек. Чем объяснить ругань на приватную x при доступе к ней из дружественной функции класса?

Автор: Mayk 31.5.2005, 18:42
yours-tester
Код

friend ostream& operator<<(ostream& stream, const test& obj);

Про дружбу не забыл?


Автор: yours-tester 1.6.2005, 08:08
Как ни странно про дружбу не забыл.
Текст программы изменился только в первых строчках как указано.

Автор: Mayk 1.6.2005, 08:33
Хмм. У меня все сработало.
Давай весь код в студию, посмотрим. И еще - что-за компилятор?

Автор: yours-tester 1.6.2005, 13:49
Вот он.
Код

#include <iostream>
using namespace std;

//using std::ostream;
//using std::cout;
//using std::endl;

class test
{
int x;

public:
test(int my_x): x(my_x) {}

friend ostream& operator<<(ostream& stream, const test& obj);
};

ostream& operator<<(ostream& stream, const test& rhs)
{
stream << rhs.x << endl;

 return stream;
}

int main()
{
test t(10);

cout << t << endl;
cout << endl << t;

return 0;
}


Компилятор VC++ 6.0 Я раньше с такой проблемой уже сталкивался, но в чём причина так и не понял. А тут гляжу похожий случай. Проверил. Та же проблема.
Стоит вместо трёх операторов using std::* применить один using namespace std, как программа перестаёт компилироваться. Если же использовать заголовки из глобального пространства h, то опять всё нормально.

Автор: Alastis 1.6.2005, 13:58
вывод - пора переходить на VC 7.1, там все это компилируется без проблем

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)