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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [?] Организация циклического списка 
:(
    Опции темы
XuTMAH
Дата 3.10.2005, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Есть следующая идея:
Код

class A : public list< T >::iterator
{
    public:
    A();
    A(list< T >::iterator iter) : list< T >::iterator(iter){}
    ~A();    
    A operator++(int);
    A& operator++();
    A operator--(int);
    A& operator--();
};
class B : list< T >
{
    private:
    
    A begin_iterator;
    
    public:
    B() : list< T >(const1), 
    begin_iterator( (*(base*)this).begin() ){};
    ~B();
    A begin() { return begin_iterator; }
};


Но есть некоторые проблемы, а именно:
1) Нужно чтобы, например, в операции ++ осуществлялось следующее: когда итератор становиться законечным (т.е. возвращамым функцией list< T >::end() ) нужно чтобы он сразу становился первым (т.е. например сделать ещё один ++ и он станет первым), тогда возникает вопрос - как узнать из самого итератора, что он законечный? возможен вариан воспользоваться try-catch но опять же вопрос - какая операция для законечного итератора может сгенерировать исключение?
Может какие-нибудь ещё способы есть узнать, что итератор законечный?
2) Нужно сохранять итератор псевдо начала этого циклического списка, т.к. "начало" у него будет потихоньку перемещаться и не один раз пройдёт через обычное начало, но представленый мной вариан не работает, даже не знаю почему.

P.S. Очень не хочется заморачиваться с new/delete и надеюсь STL спасёт меня...

Заранее благодарю за помощь.
PM MAIL   Вверх
Earnest
Дата 3.10.2005, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Цитата(XuTMAH @ 3.10.2005, 21:05)
как узнать из самого итератора, что он законечный? возможен вариан воспользоваться try-catch но опять же вопрос - какая операция для законечного итератора может сгенерировать исключение?

Никак не узнать. Реализации list::iterator могут быть разными, но чаще всего он просто хранит указатель на узел списка.
Исключения при обращении к невалидному итератору могут возникнуть, а могут и нет (смотря куда нарвешься). И вообще, это не способ: генерировать исключение, чтобы что-нибудь узнать - крайне неправильно: это очень накладно!
Cпособ один: хранить в твоем циклическом итераторе начальный и конечный итераторы исходного списка.
Ты бы сформулировал задачу поточнее, а то возникает вопрос: через конец-то ты пройдешь, а заканчивать итерирование ты как будешь? Если list::end() никогда не будет возвращаться?



--------------------
...
PM   Вверх
XuTMAH
Дата 4.10.2005, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Earnest @ 3.10.2005, 21:37)
Ты бы сформулировал задачу поточнее, а то возникает вопрос: через конец-то ты пройдешь, а заканчивать итерирование ты как будешь? Если list::end() никогда не будет возвращаться?


Заканчивать буду по равенству с псевдо началом => нужно будет оператор == перегрузить.


Немного доработав и дополнив код:

Код

#include <list>

using namespace std;

class A : public list< int >::iterator
{
    private:
    typedef list< int >::iterator base;
    base end_iterator;
    public:
    A();
    A(base iter, base end_iter) : base(iter), end_iterator(end_iter) {}
    ~A(){}    
    A operator++(int);
    A& operator++(){ ++(*(base*)this); return *this; }
    A operator--(int);
    A& operator--();
    bool operator==(A other);
};
class B : public list< int >
{
    private:
    typedef list< int > base;
    
    A begin_iterator;
    
    public:
    B();
    B(int param) : list< int >(2), 
    begin_iterator( (*(base*)this).begin(), (*(base*)this).end() )
    {
    //use param
    }
    ~B(){}
    A begin() { return begin_iterator; }
};
class C
{
    public:
    list< B > C_member;
    C() : C_member(1, B(222) ) {} ///Корректен ли такой вызов конструктора list<B> ???
    ~C(){}
};
void main()
{
    C cc;
    list< B >::iterator    bb( cc.C_member.begin() );
    A aa( (*bb).begin() );    

//    B bb(222);
//    A aa( bb.begin() ); 

    ++aa;
    ++aa;
    ++aa;
    ++aa;
    ++aa;
}



Возникла более конкретная проблема, а именно:
почему не правильно работает вариант написанный в main() (закоментированый - рабочий), т.е. при вызове конструктора "C" некорректно конструируется класс "B" (это можно проверить по непонятному значению поля B.begin_iterator) ???
PM MAIL   Вверх
Guest
Дата 5.10.2005, 02:32 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Ошибка в конструкторе:
Цитата
   begin_iterator( (*(base*)this).begin(), (*(base*)this).end() )
    {
    //use param
    }

Лично у меня компилятор выдал предупреждение:
warning C4355: 'this' : used in base member initializer list
В MSDN'е на этот счет написано:
Цитата

The this pointer is valid only within nonstatic member functions. It cannot be used in the initializer list for a base class.

The base-class constructors and class member constructors are called before this constructor. In effect, you've passed a pointer to an unconstructed object to another constructor. If those other constructors access any members or call member functions on this, the result will be undefined. You should using the this pointer until all construction has completed.

Если в кратце, то нельзя использовать this в конструкторах.
  Вверх
XuTMAH
Дата 5.10.2005, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Наверное не зря компилятор ругается...
Но почему же тогда если заменить следующий кусок кода в main()
Код

    C cc;
    list< B >::iterator    bb( cc.C_member.begin() );
    A aa( (*bb).begin() );    
//    B bb(222);
//    A aa( bb.begin() ); 


на

Код

//    C cc;
//    list< B >::iterator    bb( cc.C_member.begin() );
//    A aa( (*bb).begin() );    
    B bb(222);
    A aa( bb.begin() ); 


то всё работает без единой ошибочки, хотя
Код

    begin_iterator( (*(base*)this).begin(), (*(base*)this).end() )
    {
    //use param
    }


этот конструктор всё равно вызывается ...

Как инересно правильно написать?
Если так
Код

    begin_iterator( base::begin(), base::end() )
    {
    //use param
    }


то результат ни в одном ни в другом случае не изменяется...

Это сообщение отредактировал(а) XuTMAH - 5.10.2005, 17:13
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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