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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
14.11.2012, 12:19     Перегрузка операторов и string #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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <string>   // тип исп. в классе!
#include <vector>       // там вектор использующийся в классе
#include <algorithm> // там нужная классу функция find
#include <iostream>     //cout cin
#include "stack_iter.h"
 
using namespace std;
 
 
/*предварительное объявление класса, */
 
class stack;    // 
class stack_iterator;
 
class stack
{
friend class stack_iterator;    // говорит что класс итераторов стека может пользоваться приват объектами данного класса!
public:     
    stack(vector<string> &m); // КОНСТРУКТОР
 
    bool push (const string &elem); // добавляет эл. в конец удаляя начало
    bool pop (string &elem);        // вынимает последний эл с его удалением
    
    bool peek (string &elem) const; // читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void clear();                   // очистка стека
 
    bool find(const string &elem) const;    // поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    int count(const string &elem) const;    // сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    bool full () const; // переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    bool empty () const;    // пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    /*все функции определенные прямо при определении класса автоматом являются подставляемыми!!*/
    int size () const {return _stack.size(); } //определение функции даро прямо внутри класса остальные ф-ии просто объявлены и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void info() const;  // показывает инф о стеке,  с исп указателя this
    
    //Вызов функций итераторов!!
    typedef stack_iterator iterator; // вызывать не stack::stack_iterator а stack::iterator
    stack_iterator begin() const
    {return stack_iterator(0);} // создает объект класса stack_iterator с _index = 0
    stack_iterator end() const
    {return stack_iterator(_stack.size() -1 );} // создает объект класса stack_iterator с _index = конец стека!
private:    // доступны только функциям членам и друзьям класса, там определения функции членов!
    vector<string> _stack;  // вектор с элементами стека
 
 
    enum    
    {
       _stack_max_size = 20 // размер стека
    };  
    
};
 
// КОНСТРУКТОР
stack::stack(vector<string> &m) // инициазизация вектором
{
    vector<string>::iterator first = m.begin();
    for (int i=0;( first != m.end() && i != _stack_max_size); i++,first++)
                _stack.push_back(m[i]); // если указатель на вектор пустой то сюда вообще не зайдем
}
 
// Информация о стеке с исп указателя this
void stack::info() const 
/* *this ссылается на тот объект данного класса
* который вызвал данный метод!!!!!*/
{
if ( this->empty() ) //this УКАЗАТЕЛЬ на тот объект который вызывал этот метод!!!
    std::cout << "stack clear: size = ";
else if ( this->full() )
    std::cout << "stack full: size = ";
else 
    std::cout << "stack have elem: size = ";
cout << this->size() << endl;
}
// пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::empty() const // stack:: оператор области видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.empty(); // а это уже vector.empty()
}
// переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::full() const // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.size() == _stack_max_size/*_stack.max_size()*/; // возвращает логическое значение 1 если размер = максимальному для стека (можно задать или исп ограничения для класса вектор)
}
// добавляет эл. в конец удаляя начало
bool stack::push (const string &elem)   // добавляет эл. в конец удаляя начало
{
        if ( full() )       //full() означает stack::full() ведь мы используем область видимости класса
            return false;   // выйти с ошибкой
        _stack.push_back(elem);
        return true;
}
// вынимает последний эл с его удалением
bool stack::pop (string &elem) // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back(); // приравниваем к последнему
    _stack.pop_back();  // удаляем последний
    return true;        // операция закончена успешно
}
// читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::peek (string &elem) const
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back();// приравниваем к последнему
    return true;        // операция закончена успешно
}
// поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::find(const string &elem) const  
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    if ( std::find(_stack.begin(), _stack.end(), elem) != _stack.end() ) // если итератор найденного элемента не за пределами вектора
        return true;
    else
        return false;
}
// сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
int  stack::count(const string &elem) const 
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return 0;   // выйти с ошибкой
 
    vector<string>::const_iterator iter = _stack.begin();
    int count = 0;
 
    while ( (iter = std::find(iter, _stack.end(), elem) ) != _stack.end()   ) // FIND не класса а из STL
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    {
        ++count;
        ++iter;
// итератор указывает на последний элемент а не на end() после прибавления!?
    }
    return count;
}
// очистка стека
void stack::clear() 
{
    _stack.clear();
}
И есть класс итераторов для класса stack, для начала стек это набор элементов типа string, вот с этим и возникли проблемы, все перегруженные операторы возвращающие string дают ошибку в MVStudio 2010 не понимаю как с этим справиться подскажите пожалуйста!

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
#include <string>   // тип исп. в классе!
//#include "stack.h"
//#include <vector>     // там вектор использующийся в классе
 
/*КЛАСС ИТЕРАТОРОВ*/
class stack_iterator
{
friend class stack; // друг так как мы берем из него вектор !
public: 
    /*ИТЕРАТОРЫ и операции над ними*/
    stack_iterator(int ind) // конструктор инициализация 1 числом!!!
    {_index = ind;} // _index номер текущего элемента
 
    bool operator == (const stack_iterator & rhs) const
    {return _index == rhs._index;}  // 2 итератора равны если равны их индексы!!
    bool operator != (const stack_iterator & rhs) const
    {return !(*this == rhs);}   // через уже определенную операцию или  _index != rhs._index 2 итератора не равны если не равны их индексы!!
    string operator * (const stack_iterator & rhs) const    // разименование итератора! КАК член класса можно и как отд. функция см. за определ класса!!!!!!!!!!
    {return stack::_stack[_index];}//обращение к _elems возможно так как этот класс объявлен как друг для класса stack
    /*приф и постфиксные операторы перегруженные поэтому должны отличаться
    набором параметров, на самомо деле сам компилятор генерирует его
    поэтому делатеся все как обычно ++it; it++;*/
    string  operator ++() // префикс
    { ++_index; return stack::_stack[_index];}
    string  operator ++(int)    // постфикс
    {return stack::_stack[_index++];}
    string  operator --() // префикс
    { --_index; return stack::_stack[_index];}
    string  operator --(int)    // постфикс
    {return stack::_stack[_index--];}
private:
    int _index; //для ИТЕРАТОРОВ
 
};
 
// вариант перегруженной функции разименования не члена класса
//inline int operator * (const stack_iterator & rhs)
//{
////    rhs.chek_integrity();
//  return stack::_stack[rhs._index];
//}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.11.2012, 12:19     Перегрузка операторов и string
Посмотрите здесь:

Перегрузка операторов C++
C++ Перегрузка операторов
C++ Перегрузка операторов
C++ Перегрузка операторов
Перегрузка операторов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6172 / 2901 / 284
Регистрация: 04.12.2011
Сообщений: 7,722
Записей в блоге: 3
14.11.2012, 12:46     Перегрузка операторов и string #2
Цитата Сообщение от milvus Посмотреть сообщение
есть класс имитирующий стек, все методы проверены и работают правильно! Кроме части касающейся итераторов

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class stack;    // 
class stack_iterator;
 
class stack
{
friend class stack_iterator;    // говорит что класс итераторов стека может пользоваться приват объектами данного класса!
public:     
    stack(vector<string> &m); // КОНСТРУКТОР
 
    
private:    // доступны только функциям членам и друзьям класса, там определения функции членов!
    vector<string> _stack;  // вектор с элементами стека
 
};
 
// КОНСТРУКТОР
stack::stack(vector<string> &m) // инициазизация вектором
{
    vector<string>::iterator first = m.begin();
    for (int i=0;( first != m.end() && i != _stack_max_size); i++,first++)
                _stack.push_back(m[i]); // если указатель на вектор пустой то сюда вообще не зайдем
}
_stack - нестатический член и доступ возможен только через инициализированную переменную класса, а не через разрешение доступа ссылкой на тип, как у Вас: stack::_stack[_index];
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class stack_iterator
{
    string operator * (const stack_iterator & rhs) const    // разименование итератора! КАК член класса можно и как отд. функция см. за определ класса!!!!!!!!!!
    {return stack::_stack[_index];}//обращение к _elems возможно так как этот класс объявлен как друг для класса stack
    /*приф и постфиксные операторы перегруженные поэтому должны отличаться
    набором параметров, на самомо деле сам компилятор генерирует его
    поэтому делатеся все как обычно ++it; it++;*/
    string  operator ++() // префикс
    { ++_index; return stack::_stack[_index];}
    string  operator ++(int)    // постфикс
    {return stack::_stack[_index++];}
    string  operator --() // префикс
    { --_index; return stack::_stack[_index];}
    string  operator --(int)    // постфикс
    {return stack::_stack[_index--];}
private:
    int _index; //для ИТЕРАТОРОВ
 
};
Не лучше ли включить в класс указатель на экземпляр класса stack вроде stack* st;
и потом st->_stack[_index];
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
14.11.2012, 13:06  [ТС]     Перегрузка операторов и string #3
со static спасибо, не заметил
да наверное лучше указатели но мне надо чтоб хоть как то заработало, а потом уже можно модифицировать,
наплюнул и переписал все ни тип int, но осталась небольшая проблема

stack.h подключает stack_iter.h
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <string>   // тип исп. в классе!
#include <vector>       // там вектор использующийся в классе
#include <algorithm> // там нужная классу функция find
#include <iostream>     //cout cin
#include "stack_iter.h"
 
using namespace std;
 
 
/*предварительное объявление класса, */
 
class stack;    // 
class stack_iterator;
 
class stack
{
friend class stack_iterator;    // говорит что класс итераторов стека может пользоваться приват объектами данного класса!
public:     
    stack(vector<int> &m); // КОНСТРУКТОР
 
    bool push (const int &elem);    // добавляет эл. в конец удаляя начало
    bool pop (int &elem);       // вынимает последний эл с его удалением
    
    bool peek (int &elem) const;    // читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void clear();                   // очистка стека
 
    bool find(const int &elem) const;   // поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    int count(const int &elem) const;   // сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    bool full () const; // переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    bool empty () const;    // пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    /*все функции определенные прямо при определении класса автоматом являются подставляемыми!!*/
    int size () const {return _stack.size(); } //определение функции даро прямо внутри класса остальные ф-ии просто объявлены и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void info() const;  // показывает инф о стеке,  с исп указателя this
    
    //Вызов функций итераторов!!
    typedef stack_iterator iterator; // вызывать не stack::stack_iterator а stack::iterator
    stack_iterator begin() const
    {return stack_iterator(0);} // создает объект класса stack_iterator с _index = 0
    stack_iterator end() const
    {return stack_iterator(_stack.size() -1 );} // создает объект класса stack_iterator с _index = конец стека!
private:    // доступны только функциям членам и друзьям класса, там определения функции членов!
    static vector<int> _stack;  // вектор с элементами стека
 
 
    enum    
    {
       _stack_max_size = 20 // размер стека
    };  
    
};
 
// КОНСТРУКТОР
stack::stack(vector<int> &m) // инициазизация вектором
{
    vector<int>::iterator first = m.begin();
    for (int i=0;( first != m.end() && i != _stack_max_size); i++,first++)
                _stack.push_back(m[i]); // если указатель на вектор пустой то сюда вообще не зайдем
}
 
// Информация о стеке с исп указателя this
void stack::info() const 
/* *this ссылается на тот объект данного класса
* который вызвал данный метод!!!!!*/
{
if ( this->empty() ) //this УКАЗАТЕЛЬ на тот объект который вызывал этот метод!!!
    std::cout << "stack clear: size = ";
else if ( this->full() )
    std::cout << "stack full: size = ";
else 
    std::cout << "stack have elem: size = ";
cout << this->size() << endl;
}
// пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::empty() const // stack:: оператор области видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.empty(); // а это уже vector.empty()
}
// переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::full() const // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.size() == _stack_max_size/*_stack.max_size()*/; // возвращает логическое значение 1 если размер = максимальному для стека (можно задать или исп ограничения для класса вектор)
}
// добавляет эл. в конец удаляя начало
bool stack::push (const int &elem)  // добавляет эл. в конец удаляя начало
{
        if ( full() )       //full() означает stack::full() ведь мы используем область видимости класса
            return false;   // выйти с ошибкой
        _stack.push_back(elem);
        return true;
}
// вынимает последний эл с его удалением
bool stack::pop (int &elem) // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back(); // приравниваем к последнему
    _stack.pop_back();  // удаляем последний
    return true;        // операция закончена успешно
}
// читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::peek (int &elem) const
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back();// приравниваем к последнему
    return true;        // операция закончена успешно
}
// поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::find(const int &elem) const 
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    if ( std::find(_stack.begin(), _stack.end(), elem) != _stack.end() ) // если итератор найденного элемента не за пределами вектора
        return true;
    else
        return false;
}
// сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
int  stack::count(const int &elem) const    
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return 0;   // выйти с ошибкой
 
    vector<int>::iterator iter = _stack.begin();
    int count = 0;
 
    while ( (iter = std::find(iter, _stack.end(), elem) ) != _stack.end()   ) // FIND не класса а из STL
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    {
        ++count;
        ++iter;
// итератор указывает на последний элемент а не на end() после прибавления!?
    }
    return count;
}
// очистка стека
void stack::clear() 
{
    _stack.clear();
}
но возникает ошибка в stack_iter.h, он не знает класса stack им не видит переменной _stack
error C2027: use of undefined type 'stack'
error C2065: '_stack' : undeclared identifier
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
#include <string>   // тип исп. в классе!
 
#include <vector>       // там вектор использующийся в классе
 
//#include "stack.h"
 
class stack;
 
 
/*КЛАСС ИТЕРАТОРОВ*/
class stack_iterator
{
friend class stack; // друг так как мы берем из него вектор !
public: 
    /*ИТЕРАТОРЫ и операции над ними*/
    stack_iterator(int ind) // конструктор инициализация 1 числом!!!
    {_index = ind;} // _index номер текущего элемента
 
    bool operator == (const stack_iterator & rhs) const
    {return _index == rhs._index;}  // 2 итератора равны если равны их индексы!!
    bool operator != (const stack_iterator & rhs) const
    {return !(*this == rhs);}   // через уже определенную операцию или  _index != rhs._index 2 итератора не равны если не равны их индексы!!
    int operator * (const stack_iterator & rhs) const   // разименование итератора! КАК член класса можно и как отд. функция см. за определ класса!!!!!!!!!!
    {return stack::_stack[_index];}//обращение к _elems возможно так как этот класс объявлен как друг для класса stack
    /*приф и постфиксные операторы перегруженные поэтому должны отличаться
    набором параметров, на самомо деле сам компилятор генерирует его
    поэтому делатеся все как обычно ++it; it++;*/
    int  operator ++() // префикс
    { ++_index; return stack::_stack[_index];}
    int  operator ++(int)   // постфикс
    {return stack::_stack[_index++];}
    int  operator --() // префикс
    { --_index; return stack::_stack[_index];}
    int  operator --(int)   // постфикс
    {return stack::_stack[_index--];}
private:
    int _index; //для ИТЕРАТОРОВ
 
};
как можно сделать чтобы оба класса видели private переменные друг друга и вообще друг друга? вроде оба друзья друг для друга...
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
14.11.2012, 13:20     Перегрузка операторов и string #4
Вопрос - зачем стеку итераторы? Это концептуально другая структура данных, тут итераторы не нужны.
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
14.11.2012, 13:21  [ТС]     Перегрузка операторов и string #5
Это сугубо в учебных целях, поэтому и шаблоны не использую класса, пока до них не добрался
Вопрос остался как можно сделать чтобы оба класса видели private переменные друг друга и вообще друг друга? вроде оба друзья друг для друга...
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
14.11.2012, 13:29     Перегрузка операторов и string #6
Итераторы делаются обычно вложенными классами, чтоб можно было сделать так
C++
1
stack::iterator it = myStack.begin();
Добавлено через 4 минуты
По коду не совсем понятно, как ты собираешься использовать итератор?
А ошибки потому что так
C++
1
return stack::_stack[_index--];
делать нельзя, т.к. _stack[] не статичный член, поэтому обращаться к нему нужно через объект.

Если хочется сохранить логику итератора, то можно добавить метод типа init (stack &ob), т.е. инициализировать итератор для работы с определенным стеком. Ну и внутри итератора, естессно, хранить указатель на объект стека, с которым работаем.
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
14.11.2012, 13:34  [ТС]     Перегрузка операторов и string #7
спасибо! есть над чем подумать, вечером переделаю, посмотрим что получится!
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
15.11.2012, 15:37  [ТС]     Перегрузка операторов и string #8
Довел до рабочего состояния
Класс Стек
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <string>   // тип исп. в классе!
#include <vector>       // там вектор использующийся в классе
#include <algorithm> // там нужная классу функция find
#include <iostream>     //cout cin
 
 
using namespace std;
 
 
/*предварительное объявление класса, */
 
 
 
class stack
{
//friend class stack_iterator;  // говорит что класс итераторов стека может пользоваться приват объектами (_index) данного класса!
public:     
 
/*КЛАСС ИТЕРАТОРОВ*/
/*вложенный класс он нужен чтобы можно было объявлять тип итераторов
вот так stack::iterator*/
class stack_iterator
{
//friend class stack;   // друг так как мы берем из него вектор !
public: 
    /*ИТЕРАТОРЫ и операции над ними*/
    stack_iterator(int ind) // конструктор инициализация 1 числом!!!
        :_index (ind-1) // _index номер текущего элемента
    {} 
 
    bool operator == (const stack_iterator & rhs) const // бинарный поэтому 2 опернда один в скобках второй вызываемый
    {return _index == rhs._index;}  // 2 итератора равны если равны их индексы!!
    bool operator != (const stack_iterator & rhs) const
    {return !(*this == rhs);}   // через уже определенную операцию или  _index != rhs._index 2 итератора не равны если не равны их индексы!!
    int operator * () const // разименование итератора! КАК член класса можно и как отд. функция см. за определ класса!!!!!!!!!!
    {return stack::_stack[_index];}//обращение к _stack возможно так как этот класс объявлен как друг для класса stack
    /*приф и постфиксные операторы перегруженные поэтому должны отличаться
    набором параметров, на самомо деле сам компилятор генерирует его
    поэтому делатеся все как обычно ++it; it++;*/
    int  operator ++() // префикс
    { ++_index; return stack::_stack[_index];}
    int  operator ++(int)   // постфикс
    {return stack::_stack[_index++];}
    int  operator --() // префикс
    { --_index; return stack::_stack[_index];}
    int  operator --(int)   // постфикс
    {return stack::_stack[_index--];}
private:
    int _index; //для ИТЕРАТОРОВ
 
};
 
 
 
    friend int stack_iterator::operator * () const;
 
    stack(vector<int> &m); // КОНСТРУКТОР
    stack();
 
    bool push (const int &elem);    // добавляет эл. в конец удаляя начало
    bool pop (int &elem);       // вынимает последний эл с его удалением
    
    bool peek (int &elem) const;    // читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    void clear();                   // очистка стека
 
    bool find(const int &elem) const;   // поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    int count(const int &elem) const;   // сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    bool full () const; // переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    bool empty () const;    // пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    /*все функции определенные прямо при определении класса автоматом являются подставляемыми!!*/
    int size() const {return _stack.size(); } //определение функции даро прямо внутри класса остальные ф-ии просто объявлены и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void info() const;  // показывает инф о стеке,  с исп указателя this
    
    //для ИТЕРАТОРОВ
    typedef stack_iterator iterator; // вызывать не stack::stack_iterator а stack::iterator
 
    //Вызов функций итераторов!!
    stack_iterator begin() const
    {return stack_iterator(1);} // создает объект класса stack_iterator с _index = 0 (-1)
    stack_iterator end() const
    {return stack_iterator(_stack.size());} // создает объект класса stack_iterator с _index = конец стека!
 
private:    // доступны только функциям членам и друзьям класса, там определения функции членов!
    static vector<int> _stack;  // УКАЗАТЕЛЬ на вектор(Надо для прав. работы итераторов, чтоб не делать его static так как к нему надо обращаться из другого вектора а он должен быть связан с объектом класса stack) с элементами стека статик поэтому его надо объявить вне класса статик чтобы итераторы могли им пользоваться!!
 
 
 
 
    enum    
    {
       _stack_max_size = 20 // размер стека
    };  
    
};
 
// КОНСТРУКТОР
stack::stack(vector<int> &m) // инициазизация вектором
{
    vector<int>::iterator first = m.begin();
    for (int i=0;( first != m.end() && i != _stack_max_size); i++,first++)
                _stack.push_back(m[i]); // если указатель на вектор пустой то сюда вообще не зайдем
}
stack::stack(){} // если создат стек без параметров то надо его инициализировать пустым вектором _stack когда уберу static
 
// Информация о стеке с исп указателя this
void stack::info() const 
/* *this ссылается на тот объект данного класса
* который вызвал данный метод!!!!!*/
{
if ( this->empty() ) //this УКАЗАТЕЛЬ на тот объект который вызывал этот метод!!!
    std::cout << "stack clear: size = ";
else if ( this->full() )
    std::cout << "stack full: size = ";
else 
    std::cout << "stack have elem: size = ";
cout << this->size() << endl;
}
// пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::empty() const // stack:: оператор области видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.empty(); // а это уже vector.empty()
}
// переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::full() const // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.size() == _stack_max_size/*_stack.max_size()*/; // возвращает логическое значение 1 если размер = максимальному для стека (можно задать или исп ограничения для класса вектор)
}
// добавляет эл. в конец удаляя начало
bool stack::push (const int &elem)  // добавляет эл. в конец удаляя начало
{
        if ( full() )       //full() означает stack::full() ведь мы используем область видимости класса
            return false;   // выйти с ошибкой
        _stack.push_back(elem);
        return true;
}
// вынимает последний эл с его удалением
bool stack::pop (int &elem) // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back(); // приравниваем к последнему
    _stack.pop_back();  // удаляем последний
    return true;        // операция закончена успешно
}
// читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::peek (int &elem) const
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back();// приравниваем к последнему
    return true;        // операция закончена успешно
}
// поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::find(const int &elem) const 
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    if ( std::find(_stack.begin(), _stack.end(), elem) != _stack.end() ) // если итератор найденного элемента не за пределами вектора
        return true;
    else
        return false;
}
// сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
int  stack::count(const int &elem) const    
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return 0;   // выйти с ошибкой
 
    vector<int>::iterator iter = _stack.begin();
    int count = 0;
 
    while ( (iter = std::find(iter, _stack.end(), elem) ) != _stack.end()   ) // FIND не класса а из STL
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    {
        ++count;
        ++iter;
// итератор указывает на последний элемент а не на end() после прибавления!?
    }
    return count;
}
// очистка стека
void stack::clear() 
{
    _stack.clear();
}
 
vector<int> stack::_stack;  // явное объявление static вектора некоторого класса!
Класс Итераторов в нем

Проблема в том что работает только пока вектор _stack static но мне хочется чтобы каждый объект класса имел свой вектор
Как предлагал Kastaneda init (stack &ob) чесно говоря в инете не нашел ничего про эту инициализацию, если не сложно вставте пожалуйста код в класс чтобы инициализировать _stack некоторым объектом, и объясните как она работает
вот пример тестовой программы
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "stack.h"      // мой класс имитирующий работу стека памяти особ реализация методов класса
#include <iostream>     //cout cin
#include <string>
#include <vector>
 
using namespace std;
 
int main()
{
int i=0;
int temp;
string temp2[] = 
{"1","2","3","4","5","6","7","8","9",
"10","11","12","13","14","15","16","17",
"18","19","20","21","22"};
int temp3[] = 
{1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,
16,17,18,19,20,
21,22};
vector<int> vec(temp3, temp3 + 22);
/*имея только предварительное объявление класса уже можно ссылаться на этот ТИП
но не на элементы его и не присваивая этот класс переменным*/
stack *pi = 0; //имя класса используется как тип переменной, тут пи это указатель на объект типа стек
 
 
/********************************************  Объявление и ИНИЦИАЛИЗАЦИЯ объекта класса стек */
stack s = vec;  // возможно только после определения ИНИЦИАЛИЗАЦИЯ ВЕКТОРОМ!
s.info();   // вывод инф о стеке
s.clear();
s.info();;  // вывод инф о стеке
 
/********************************************  Заполнение */
for (int i =0; i<50; i++)
{
temp = (i+1)*10 ;   // найденная в инете шабл. функция перевода int - str
    if ( ! s.full())    // если стек не полный
        s.push(temp);   // добоавить
    else 
        break;  // по заполнении выйти из цикла
}
 
s.info();
stack s2 /*= s*/;   //stack s2(s1);
 
/********************************************  чтение с удалением */
s2.pop(temp);
cout << " del " << temp << endl;
 
s2.pop(temp);
s2.pop(temp);
/********************************************  чтение без удаления */
 
s2.peek(temp);
cout << " read not del " << temp << endl;
s2.info();
 
/********************************************  поиск и подсчет */
s2.push(temp);  // добавим 2 копию элемента темп
    if ( s2.find(temp)) // если элемент найден
        cout << " element " << temp << " present in stack: " << s2.count(temp) << " times " << endl;
s2.push(temp);  // добавим 3 копию элемента темп
s2.push(temp);  // добавим 4 копию элемента темп    
    if ( s2.find(temp)) // если элемент найден
        cout << " element " << temp << " present in stack: " << s2.count(temp) << " times " << endl;
 
/********************************************  вложенный класс итераторов */
cout << "s2 contain:" << endl;
stack::iterator fir = s2.begin();
stack::iterator end = s2.end();
while ( fir != end )
{
    cout << *fir << " ";
    fir++;
}
cout << endl;
cout << "s contain:" << endl;
 fir = s.begin();
 end = s.end();
while ( end != fir )
{
    --end;
    cout << *end << " ";
 
}
 
 
/********************************************  Конец */
cin >> i;
return 0;   // явный выход без ошибок
}
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6172 / 2901 / 284
Регистрация: 04.12.2011
Сообщений: 7,722
Записей в блоге: 3
15.11.2012, 15:58     Перегрузка операторов и string #9
Поспешил - удалил.
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
15.11.2012, 17:09  [ТС]     Перегрузка операторов и string #10
Up ну может хоть концептуально кто-нибудь может объяснить как работает init() и как можно из одного класса добраться до нестатического объекта другого
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
15.11.2012, 17:20     Перегрузка операторов и string #11
Цитата Сообщение от milvus Посмотреть сообщение
Up ну может хоть концептуально кто-нибудь может объяснить как работает init()
Раз ты перенес итератор внутрь стека, то ни чего инициализировать уже не надо.
А почему с нестатичным stack'ом не работает? Что пишет?

Если интересно, вот писал когда-то давно для учебы, там стек (кстати не совсем правильно сделан) со вложенным классом итератор.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.11.2012, 20:34     Перегрузка операторов и string
Еще ссылки по теме:

C++ Перегрузка операторов сравнения и разницы. Класс String
C++ Перегрузка операторов
C++ Перегрузка операторов. Класс String

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

Или воспользуйтесь поиском по форуму:
milvus
0 / 0 / 0
Регистрация: 14.11.2012
Сообщений: 35
16.11.2012, 20:34  [ТС]     Перегрузка операторов и string #12
\stack_iter.h(15): error C2597: illegal reference to non-static member 'stack::_stack'
\stack_iter.h(15): error C3867: 'stack::_stack': function call missing argument list; use '&stack::_stack' to create a pointer to member
\stack_iter.h(15): error C2109: subscript requires array or pointer type

и так на каждый перегруженный оператор итераторов

Добавлено через 4 часа 44 минуты
Kastaneda спасибо, посмотрел но на данном этапе не все понял в коде, мне проще добить свой вариант да и хотелось бы все таки разобраться с моими ошибками
Вот как я сделал, в чем я не прав???
Добавил в класс итераторов переменную
C++
1
static stack _obj;
в которую при вызове
C++
1
stack1.begin()
кладется объект стека который вызвал этот метод
далее при любой операции с итераторами я ссылался на этот объект например
C++
1
2
int operator * () const
{return _obj._stack[_index];}
Откудато появилась ошибка при работе с обычным итератором вектора, раньше все работало нормально
vector<int>::iterator iter = _stack.begin();

C2440: 'initializing' : cannot convert from 'std::_Vector_const_iterator<_Myvec>' to 'std::_Vector_iterator<_Myvec>'

меняю на vector<int>::const_iterator iter = _stack.begin();

появляется вот это
error LNK2001: unresolved external symbol "private: static class stack stack::stack_iterator::_obj" (?_obj@stack_iterator@stack@@0V2@A)


вот исходники
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include <string>   // тип исп. в классе!
#include <vector>       // там вектор использующийся в классе
#include <algorithm> // там нужная классу функция find
#include <iostream>     //cout cin
 
 
using namespace std;
 
 
/*предварительное объявление класса, */
 
//class stack;  // объявление
//class stack_iterator;
 
class stack
{
friend class stack_iterator;    // говорит что класс итераторов стека может пользоваться приват объектами (_index) данного класса!
public:     
 
/*КЛАСС ИТЕРАТОРОВ*/
/*вложенный класс он нужен чтобы можно было объявлять тип итераторов
вот так stack::iterator*/
 
class stack_iterator
{
friend class stack; // друг так как мы берем из него вектор !
public: 
    /*ИТЕРАТОРЫ и операции над ними*/
    stack_iterator(int ind) // конструктор инициализация 1 числом!!!
        :_index (ind-1) // _index номер текущего элемента
    {} 
 
    bool operator == (const stack_iterator & rhs) const // бинарный поэтому 2 опернда один в скобках второй вызываемый
    {return _index == rhs._index;}  // 2 итератора равны если равны их индексы!!
    bool operator != (const stack_iterator & rhs) const
    {return !(*this == rhs);}   // через уже определенную операцию или  _index != rhs._index 2 итератора не равны если не равны их индексы!!
    int operator * () const // разименование итератора! КАК член класса можно и как отд. функция см. за определ класса!!!!!!!!!!
    {return _obj._stack[_index];}//обращение к _elems возможно так как этот класс объявлен как друг для класса stack
    /*приф и постфиксные операторы перегруженные поэтому должны отличаться
    набором параметров, на самомо деле сам компилятор генерирует его
    поэтому делатеся все как обычно ++it; it++;*/
    int  operator ++() // префикс
    { ++_index; return _obj._stack[_index];}
    int  operator ++(int)   // постфикс
    {return _obj._stack[_index++];}
    int  operator --() // префикс
    { --_index; return _obj._stack[_index];}
    int  operator --(int)   // постфикс
    {return _obj._stack[_index--];}
private:
    int _index; //для ИТЕРАТОРОВ
    static stack _obj; // указатель на объект класса стек который инициализируется при объявлении st1.begin() например
};
 
 
    friend int stack_iterator::operator * () const;
 
    stack(vector<int> &m); // КОНСТРУКТОР
    stack();
 
    bool push (const int &elem);    // добавляет эл. в конец удаляя начало
    bool pop (int &elem);       // вынимает последний эл с его удалением
    
    bool peek (int &elem) const;    // читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    void clear();                   // очистка стека
 
    bool find(const int &elem) const;   // поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    int count(const int &elem) const;   // сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
 
    bool full () const; // переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    bool empty () const;    // пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    /*все функции определенные прямо при определении класса автоматом являются подставляемыми!!*/
    int size() const {return _stack.size(); } //определение функции даро прямо внутри класса остальные ф-ии просто объявлены и говорит что этот мето не изменяет данные в переменной этого класса!!!!
    void info() const;  // показывает инф о стеке,  с исп указателя this
    
    //для ИТЕРАТОРОВ
    typedef stack_iterator iterator; // вызывать не stack::stack_iterator а stack::iterator
 
    //Вызов функций итераторов!!
    stack_iterator begin() const
    {
        stack_iterator::_obj = *this;
        return stack_iterator(1);// создает объект класса stack_iterator с _index = 0 (-1)
    } 
    stack_iterator end() const
    {
        stack_iterator::_obj = *this;
        return stack_iterator(_stack.size());// создает объект класса stack_iterator с _index = конец стека!
    } 
 
private:    // доступны только функциям членам и друзьям класса, там определения функции членов!
    /*static*/ vector<int> _stack;  // вектор с элементами стека статик поэтому его надо объявить вне класса статик чтобы итераторы могли им пользоваться!!
 
 
 
 
    enum    
    {
       _stack_max_size = 20 // размер стека
    };  
    
};
 
// КОНСТРУКТОР
stack::stack(vector<int> &m) // инициазизация вектором
{
    vector<int>::iterator first = m.begin();
    for (int i=0;( first != m.end() && i != _stack_max_size); i++,first++)
                _stack.push_back(m[i]); // если указатель на вектор пустой то сюда вообще не зайдем
}
stack::stack(){} // если создат стек без параметров то надо его инициализировать пустым вектором _stack когда уберу static
 
// Информация о стеке с исп указателя this
void stack::info() const 
/* *this ссылается на тот объект данного класса
* который вызвал данный метод!!!!!*/
{
if ( this->empty() ) //this УКАЗАТЕЛЬ на тот объект который вызывал этот метод!!!
    std::cout << "stack clear: size = ";
else if ( this->full() )
    std::cout << "stack full: size = ";
else 
    std::cout << "stack have elem: size = ";
cout << this->size() << endl;
}
// пустой и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::empty() const // stack:: оператор области видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.empty(); // а это уже vector.empty()
}
// переполнение и говорит что этот мето не изменяет данные в переменной этого класса!!!!
inline bool stack::full() const // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    return _stack.size() == _stack_max_size/*_stack.max_size()*/; // возвращает логическое значение 1 если размер = максимальному для стека (можно задать или исп ограничения для класса вектор)
}
// добавляет эл. в конец удаляя начало
bool stack::push (const int &elem)  // добавляет эл. в конец удаляя начало
{
        if ( full() )       //full() означает stack::full() ведь мы используем область видимости класса
            return false;   // выйти с ошибкой
        _stack.push_back(elem);
        return true;
}
// вынимает последний эл с его удалением
bool stack::pop (int &elem) // stack:: область видимости класса это позволяет ее отличать скажем от vector.empty()
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back(); // приравниваем к последнему
    _stack.pop_back();  // удаляем последний
    return true;        // операция закончена успешно
}
// читает последний элемент без удаления и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::peek (int &elem) const
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
    elem = _stack.back();// приравниваем к последнему
    return true;        // операция закончена успешно
}
// поиск заданного элемента по стеку и говорит что этот мето не изменяет данные в переменной этого класса!!!!
bool stack::find(const int &elem) const 
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return false;   // выйти с ошибкой
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    if ( std::find(_stack.begin(), _stack.end(), elem) != _stack.end() ) // если итератор найденного элемента не за пределами вектора
        return true;
    else
        return false;
}
// сколько раз этот элемент встречается в стеке! и говорит что этот мето не изменяет данные в переменной этого класса!!!!
int  stack::count(const int &elem) const    
{
    if ( empty() )      //empty() означает stack.empty() ведь мы используем область видимости класса
        return 0;   // выйти с ошибкой
 
    vector<int>::const_iterator iter = _stack.begin();
    int count = 0;
 
    while ( (iter = std::find(iter, _stack.end(), elem) ) != _stack.end()   ) // FIND не класса а из STL
/*std:: если явно не писать то будет вызваться find класса а не стандартный find*/
    {
        ++count;
        ++iter;
// итератор указывает на последний элемент а не на end() после прибавления!?
    }
    return count;
}
// очистка стека
void stack::clear() 
{
    _stack.clear();
}
 
//vector<int> stack::_stack;    // явное объявление static вектора некоторого класса!
stack _obj;// явное объявление static указатель на объект класса стек который инициализируется при объявлении st1.begin() например
Добавлено через 22 часа 22 минуты
Нет никаких идей? Эта тема мне покоя не дает, не могу читать книгу дальше, пока с этим не разберусь!
Yandex
Объявления
16.11.2012, 20:34     Перегрузка операторов и string
Ответ Создать тему
Опции темы

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