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

Перегрузка << для вектора - C++

Восстановить пароль Регистрация
 
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
13.12.2010, 22:05     Перегрузка << для вектора #1
Добрый день,
перегружаю оператор "<<" для вектора который содержит строки так вот - возник вопрос почему
перегрузить можно только вне класса? например
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
29
30
31
32
33
34
35
36
#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>
 
using std::cout;
using std::cin;
using std::endl;
 
typedef std::vector<std::string> str_vect;
 
 
class my_vector : public str_vect
{
public:
    my_vector operator<<(std::string str)
    {
        this->push_back(str);
        return *this;
    }
};
 
int main ()
{
    my_vector str_vect;
 
    // fill string vector
    str_vect << std::string("zero") << std::string("one") << std::string("two") << std::string("three") << std::string("four")
            << std::string("five") << std::string("six") << std::string("seven") << std::string("eight") << std::string("nine");
 
    cout << str_vect.back() << endl;
 
    system("PAUSE");
    return 0;
 
}
В результате выводит "zero", что говорит о том что операторная ф-ция сработала только раз, а если перегрузить вне класса и передать два параметра все норм, напр.
C++
1
2
3
4
5
str_vect& operator<<(str_vect &vect, std::string str)
{
    vect.push_back(str);
    return vect;
}
почему нельзя перегружать через ф-цию-член?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Aye Aye
 Аватар для Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
14.12.2010, 09:01     Перегрузка << для вектора #2
Вот этот оператор:
C++
1
my_vector operator<<(std::string str)
что возвращает? новый объект, соответственно здесь:
C++
1
2
tr_vect << std::string("zero") << std::string("one") << std::string("two") << std::string("three") << std::string("four")
            << std::string("five") << std::string("six") << std::string("seven") << std::string("eight") << std::string("nine");
создается дофига временных объектов типа str_vect, в каждый из который вставляется строка.
Значит что должен возвращать operator<<(std::string str)?
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
14.12.2010, 10:31  [ТС]     Перегрузка << для вектора #3
Цитата Сообщение от Aye Aye Посмотреть сообщение
что возвращает? новый объект, соответственно здесь:
спасибо исправил, вот так вот работает:
C++
1
2
3
4
5
my_vector& operator<<(std::string str)
    {
        this->push_back(str);
        return *this;
    }
Можете еще кое-что уяснить мне, при первом вызове str_vect << std::string("zero") модифицируется объект str_vect через указатель this, то есть в него записывается строка
this->push_back(str); я так понимаю что следующий вызов будет str_vect << std::string("one")(так как временный объект уничтожается сразу после возвращении с ф-ции) так почему тогда не сохраняется строка "one" в вектор если мы ее записываем через this?

или следующий вызов << std::string("one") вызывается не с str_vect?
Aye Aye
 Аватар для Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
14.12.2010, 11:05     Перегрузка << для вектора #4
потому, что в не исправленном операторе она записывается в другой временный вектор, который тут же уничтожается, твой tr_vect вызывает всего один operator<<, остальные операторы вызываются временными объектами.
например запись: a + b
значит тоже что и запись: a.operator+(b)
Вот смотри, до того как ты исправил у тебя было так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
my_vector tr_vect; // глобальная по отношению к последующим областям видимости
{
    tr_vect << std::string("zero");
}
{
    my_vector new_temporary_variable1; // локальная
    new_temporary_variable1 << std::string("one");
}
{
    my_vector new_temporary_variable2; // локальная
    new_temporary_variable2 << std::string("two")
}
а после исправления стало так:
C++
1
((tr_vect.operaor<<(std::string("zero"))).operator<<(std::string("one"))).operator<<(std::string("two")) // и т. д.
типа сначала оператор вызывается для из tr_vect для строки "zero" и возвращает ссылку на этот же объект, потом этот объект взят в скобочки, видишь... из него вызывается второй оператор для "one" и так далее.

Добавлено через 19 минут
я тут ошибся случайно в посте №2
Цитата Сообщение от Aye Aye Посмотреть сообщение
создается дофига временных объектов типа str_vect, в каждый из который вставляется строка.
создаются объекты типа my_vector конечно же!
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
14.12.2010, 11:17  [ТС]     Перегрузка << для вектора #5
Цитата Сообщение от Aye Aye Посмотреть сообщение
потому, что в не исправленном операторе она записывается в другой временный вектор, который тут же уничтожается, твой tr_vect вызывает всего один operator<<, остальные операторы вызываются временными объектами.
сделал вывод деструктора, конструктора и операторной ф-ции

то есть уничтожение временных объектов происходит после строчки:
C++
1
2
str_vect << std::string("zero") << std::string("one") << std::string("two") << std::string("three") << std::string("four")
            << std::string("five") << std::string("six") << std::string("seven") << std::string("eight") << std::string("nine");
возникает тут сразу вопрос - по идее самый последний временный объект, который был передан операторной ф-ции вот тут: << std::string("nine"); - будет содержат полный вектор(то есть с строки "zero" ... "nine")? я имею ввиду каждый следующий временный объект будет накапливать строки?

и еще вопрос - временные объекты всегда уничтожаются после конца инструкции которая их использует, а не сразу после выхода с ф-ции?
Спасибо еще раз
Миниатюры
Перегрузка << для вектора  
Aye Aye
 Аватар для Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
14.12.2010, 11:41     Перегрузка << для вектора #6
Цитата Сообщение от norge_goth Посмотреть сообщение
...самый последний временный объект, который был передан операторной ф-ции вот тут: << std::string("nine"); - будет содержат полный вектор...
нет, последний временный объект не будет содержать все строки. Почему он должен? Ведь из него вызовется всего один оператор для одной строки. Каждый раз временный объект новый - сконструированный конструктором по умолчанию. Наверно тебя вводит в заблуждение указатель this? Он для каждого объекта свой собственный.
если есть:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A{
    int x;
public:
    void foo(int x)
    {
         this->x = x;
    }
};
// и объекты класса А
A aaa, bbb;
// то вызов
aaa.foo(100500);
// совершается так: foo(&aaa,100500); как бы void foo(A *this, int x)
// вызов
bbb.foo(111111);
// совершается так: foo(&bbb,111111); как бы void foo(A *this, int x)
 
// и в этой точке программы aaa.x != bbb.x
// aaa.x == 100500
// bbb.x == 111111
то есть для каждого вызова метода указатель на объект, из которого он был вызван, ему передается каждый раз свой - с адресом этого самого объекта.

и на второй вопрос - да. Деструкторы будут вызваны для временных объектов сразу, как только завершится вычисление выражения в котором эти временные объекты участвуют. Вот их столько и вызвалось.
Незачто.
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
14.12.2010, 13:14  [ТС]     Перегрузка << для вектора #7
Цитата Сообщение от Aye Aye Посмотреть сообщение
нет, последний временный объект не будет содержать все строки. Почему он должен? Ведь из него вызовется всего один оператор для одной строки. Каждый раз временный объект новый - сконструированный конструктором по умолчанию. Наверно тебя вводит в заблуждение указатель this? Он для каждого объекта свой собственный.
у вас тут все понятно, каждый раз конструируется новый объект, а у меня объект (я так предполагаю) в ретурне просто копируется, но не конструируется, чему свидетельствует только один вызов конструктора(вначале):
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>
 
using std::cout;
using std::cin;
using std::endl;
 
typedef std::vector<std::string> str_vect;
 
 
class my_vector : public str_vect
{
    static int i;
    std::vector<std::string>::iterator p_iter;
public:
    my_vector() { cout << "Object created" << endl; }
    ~my_vector() { cout << "Object destroyed" << endl; }
    my_vector operator<<(std::string str)
    {
        cout << "Operator << " << endl;
        this->push_back(str);
        ++i;
        
        //vector output 
        cout << i << ". ";
        p_iter = this->begin();
 
        while (p_iter != this->end())
        {
            cout << *p_iter << '\t';
            ++p_iter;
        }
 
        cout << endl;
        return *this;
    }
};
 
int my_vector::i;
 
int main ()
{
    my_vector str_vect;
 
    // fill string vector
    str_vect << std::string("zero") << std::string("one") << std::string("two") << std::string("three") << std::string("four")
        << std::string("five") << std::string("six") << std::string("seven") << std::string("eight") << std::string("nine");
 
 
    cout << str_vect.size() << endl;
 
    system("PAUSE");
    return 0;
 
}
и поэтому каждый оператор << посредством указателя this и ф-ции push_back добавляет к уже имеющейся строке новую

Если сделать так :
C++
1
2
str_vect = str_vect << std::string("zero") << std::string("one") << std::string("two") << std::string("three") << std::string("four")
        << std::string("five") << std::string("six") << std::string("seven") << std::string("eight") << std::string
то после
C++
1
cout << str_vect.size() << endl;
выведет 10
Миниатюры
Перегрузка << для вектора  
Aye Aye
 Аватар для Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
14.12.2010, 13:26     Перегрузка << для вектора #8
Цитата Сообщение от norge_goth Посмотреть сообщение
каждый раз конструируется новый объект, а у меня объект (я так предполагаю) в ретурне просто копируется, но не конструируется,
еще как конструируется, просто ты не в тот конструктор вписал вывод на экран.
вот этот конструктор:
C++
1
my_vector() { cout << "Object created" << endl; }
какие аргументы принимает? никаких, а тут:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    my_vector operator<<(std::string str)
    {
        cout << "Operator << " << endl;
        this->push_back(str);
        ++i;
        
        //vector output 
        cout << i << ". ";
        p_iter = this->begin();
 
        while (p_iter != this->end())
        {
            cout << *p_iter << '\t';
            ++p_iter;
        }
 
        cout << endl;
        return *this; // вот тут вызывается конструктор копирования для конструирования нового объекта.
    }
какой конструктор вызывается? правильно my_vector(const my_vector&).
Цитата Сообщение от norge_goth Посмотреть сообщение
Если сделать так : ...
я понял, моя оплошность, временные объекты же передаются один к другому, каждый текущий объект - копируется для создания следующего. Это как раз потому что:
Цитата Сообщение от Aye Aye Посмотреть сообщение
((tr_vect.operaor<<(std::string("zero"))).operator<<(std::string("one"))).operator<<(std::string("two")) // и т. д.
никто не отменял. я немного ошибся с кем не бывает.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.12.2010, 13:45     Перегрузка << для вектора
Еще ссылки по теме:

Составить главную программу и функцию. Для данного вектора А(М) найти количество неповторяющихся элементов вектора C++
C++ Перегрузка умножения вектора (STL) на вещественное число
Перегрузка оператора умножения в шаблоне класса вектора (Visual Studio 2013) C++

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

Или воспользуйтесь поиском по форуму:
norge_goth
62 / 62 / 7
Регистрация: 27.01.2009
Сообщений: 279
14.12.2010, 13:45  [ТС]     Перегрузка << для вектора #9
Цитата Сообщение от Aye Aye Посмотреть сообщение
еще как конструируется, просто ты не в тот конструктор вписал вывод на экран.
вот этот конструктор:
да вы действительно правы, чет совсем забыл про конструктор копирования... в плюсах столько нюансов, что складывается впечатление будто действительно вселенная написана на нем
Yandex
Объявления
14.12.2010, 13:45     Перегрузка << для вектора
Ответ Создать тему
Опции темы

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