Страница 1 из 3
Insert с иттератором
Добавлено: 18 янв 2016, 09:59
Сионист
Пусть есть некоторый класс контейнера, а в нём класс иттератора и функция-член Insert, принимающая иттератор элемента, после которого должна вставить новый элемент. Предположим, функция вызвана от одного члена контейнера, а иттератор принадлежит другому. То есть:
Код: Выделить всё
TContaner c1, c2;
TContaner::itterator Itterator;
...
Itterator=c2.Begin();
++Itterator;
c1.Insert(Itterator, 21);
, где TContaner - некоторый класс контейнера. Опишите правильное поведение функции-члена Insert для этого случая. Как его реализовать?
Re: Insert с иттератором
Добавлено: 18 янв 2016, 14:33
Romeo
Я бы сделал так: пробегаем контейнер, пытаясь найти в нём поинтер, инкапсулированный в итераторе. Если находим, то вставляем новый элемент после него. Если не находим - то исключение.
Re: Insert с иттератором
Добавлено: 18 янв 2016, 17:25
Сионист
Сложноват Insert для дерева/списка получается. И слишком тормознутый. Для массива ещё ладно, вычесть адрес нулевого элемента и сравнить с количеством.
Re: Insert с иттератором
Добавлено: 18 янв 2016, 18:00
Romeo
Ну в данной реализации, которую предложил WinMain, можно и проще. Там ведь итератор содержит указатель на контейнер. Достаточно сравнить адреса и можно уже кидаться исключением, если не совпадают.
Re: Insert с иттератором
Добавлено: 21 янв 2016, 12:05
Сионист
О какой реализации речь?
Re: Insert с иттератором
Добавлено: 21 янв 2016, 14:11
Romeo
О реализации вот из этой
темы. Сообщение №8.
Вот поэтому мне и не нравится, что ты генерируешь на каждый чих новую тему. Писал бы о самописном классе с итератором в одной теме - было бы понятно по контексту о какой реализации речь.
Re: Insert с иттератором
Добавлено: 21 янв 2016, 14:24
Сионист
Код: Выделить всё
class Iterator
{
public:
Iterator() : m_node(nullptr)
{
}
Iterator(Node *n)
{
m_node = n;
}
void operator++()
{
if (m_node != nullptr)
{
m_node = m_node->Next;
}
}
bool operator!=(const Iterator& it)
{
return (m_node != it.m_node);
}
private:
Node *m_node;
};
. Ну и где здесь в итераторе инфа о контейнере?
Писал бы о самописном классе с итератором в одной теме - было бы понятно по контексту о какой реализации речь.
Ровно столько же. О том, что речь о какой то реализации в одной из моих тем, как раз было понятно и так. Вот только ни в одной из них мне не попадались реализации с указанной особенностью.
Re: Insert с иттератором
Добавлено: 21 янв 2016, 14:25
Сионист
Что именно бросать в каждом случае:
Код: Выделить всё
class TList
{
public:
class TItem;
class Iterator
{
private:
friend class TList;
friend class TItem;
TList *Owner;
TItem *Pointer;
Iterator (TList *Owner, TItem *Pointer)
{
this->Owner =Owner;
this->Pointer=Pointer;
}
public:
Iterator ()
{
Owner =nullptr;
Pointer=nullptr;
}
Iterator operator ++()
{
if (Owner==nullptr)
{
throw;
}
if (Pointer!=nullptr)
{
Pointer=Pointer->Next;
}
return *this;
}
int &operator * ()
{
if (Owner==nullptr)
{
throw;
}
if (Pointer==nullptr)
{
throw;
}
return Pointer->Data;
}
bool operator != (const Iterator &Right)
{
if ((Owner==nullptr)||(Right.Owner==nullptr))
{
throw;
}
return ((Owner==Right.Owner)&&(Pointer!=Right.Pointer));
}
};
class TItem
{
friend class TList;
friend class Iterator;
private:
TItem *Next;
public:
int Data;
};
private:
TItem *First;
TItem *Last;
public:
TList()
{
First=nullptr;
Last =nullptr;
}
~TList()
{
TItem *Next;
for (Next=First->Next; Next!=nullptr; First=Next, Next=First->Next)
{
delete First;
}
Last=nullptr;
}
Iterator Insert (const Iterator &After, const int &Data)
{
TItem *Item;
if (After.Owner==nullptr)
{
throw;
}
if (After.Owner!=this)
{
throw;
}
Item=new TItem;
Item->Data=Data;
if (After.Pointer==nullptr)
{
if (Last!=nullptr)
{
Last->Next=Item;
}
Last=Item;
Item->Next=nullptr;
}
if (First==nullptr)
{
First=Item;
}
return Iterator(this, Item->Next);
}
Iterator Begin()
{
return Iterator(this, First);
}
Iterator End ()
{
return Iterator(this, nullptr);
}
Iterator Find(const int &Value)
{
TItem *Item;
for (Item=First; Item!=nullptr; Item=Item->Next)
{
if ((Item->Data)==Value)
{
return Iterator(this, Item);
}
}
return Iterator(this, nullptr);
}
};
?
Re: Insert с иттератором
Добавлено: 21 янв 2016, 14:36
Romeo
Сионист писал(а):Ну и где здесь в итераторе инфа о контейнере?
Да, действительно нет. Значит мне показалось.
Сионист писал(а):Что именно бросать в каждом случае
Можно сделать свой класс-исключение и везде бросать его. Класс сделать вложенным, как и класс-итератор. WinMain уже давал пример, в котором был объявлен класс-исключение, который наследовался от std::exception.
Есть ещё замечание по коду. Везде делать проверку if (Owner==nullptr) и кидать исключение, не нужно. Достаточно сделать эту проверку в конструкторе итератора, ведь дальше Owner нигде в коде не меняется. И, кстати, этот факт можно подчеркнуть, объявив поле вот так:
или вообще сделать ссылкой.
Re: Insert с иттератором
Добавлено: 21 янв 2016, 15:04
WinMain
Вариант моего контейнера с исключениями находится
в этой теме.
Из-за того, что обсуждение одного по сути вопроса разнесено на множество тем форума, нарушается целостность контекста обсуждения. Потом сложно будет собрать воедино все предложения по данной теме или появится множество повторяющихся постов от разных участников.