class SomeClass
{
......
};
SomeClass SomeClassArray[1024]; // 1024개의 배열
이때 SomeClassArray의 모든 원소를 하나씩 꺼내기 위한 일반적인 방법은 다음과 같습니다.
int k;
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Read();
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Process();
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Write();
for(k = 0; k < 1024; ++k)
Func(&SomeClassArray[k]);
하지만 이 방법만 있는 것은 아니죠. SomeClassArray의 모든 원소를 하나씩 꺼내기 위한 다른 한가지 방법은 반복자(Iterator)를 사용하는 방법도 있습니다.
class SomeClassIterator // 반복자 정의
{
private :
SomeClass *SomeClassArray;
int Size;
int Finger;
public :
SomeClassIterator(SomeClass *arr, int size)
{
SomeClassArray = arr;
Size = size;
Finger = 0;
}
~SomeClassIterator(void)
{
}
SomeClass *operator ->(void)
{
return Finger >= Size ? nullptr : SomeClassArray[Finger];
}
SomeClass *operator *(void)
{
return Finger >= Size ? nullptr : SomeClassArray[Finger];
}
void operator ++(void)
{
++Finger;
}
void Home(void)
{
Finger = 0;
}
bool IsEnd(void)
{
return Finger >= Size;
}
};
SomeClassIterator iter(SomeClassArray, 1024); // 반복자 선언
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Read();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Process();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Write();
for(iter.Home(); !iter.IsEnd(); ++iter)
Func(*iter);
그런데 반복자는 왜 사용해야 할까요? 위에서 보듯 SomeClassIterator라는 클래스가 추가되는 등 오히려 더 복잡해지기만 하는데 말입니다.
만약 SomeClass와 SomeClassArray가 다음과 같이 바뀌면 어떻게 될까요?
class SomeClass
{
......
};
SomeClass2
{
....
SomeClass Member;
};
SomeClass2 SomeClassArray[1024]; // 1024개의 배열
이 경우에 일반적인 for 루프를 사용했다면 다음과 같이 바꿔야 합니다.
int k;
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Member.Read();
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Member.Process();
for(k = 0; k < 1024; ++k)
SomeClassArray[k].Member.Write();
for(k = 0; k < 1024; ++k)
Func(&SomeClassArray[k].Member);
더구나 저런 루프는 프로그램 전체에 흩어져 있을 것이므로 모든 for루프를 찾아 고치지 않으면 안되죠.
만약 iterator를 사용한다면
class SomeClassIterator // 반복자 정의
{
private :
SomeClass2 *SomeClassArray;
int Size;
int Finger;
public :
SomeClassIterator(SomeClass2 *arr, int size)
{
SomeClassArray = arr;
Size = size;
Finger = 0;
}
~SomeClassIterator(void)
{
}
SomeClass *operator ->(void)
{
return Finger >= Size ? nullptr : SomeClassArray[Finger].Member;
}
SomeClass *operator *(void)
{
return Finger >= Size ? nullptr : SomeClassArray[Finger].Member;
}
void operator ++(void)
{
++Finger;
}
void Home(void)
{
Finger = 0;
}
bool IsEnd(void)
{
return Finger >= Size;
}
};
SomeClassIterator iter(SomeClassArray, 1024); // 반복자 선언
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Read();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Process();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Write();
for(iter.Home(); !iter.IsEnd(); ++iter)
Func(*iter);
와 같이 SomeClassIterator클래스만 수정하면 프로그램의 다른 부분은 전혀 고칠 필요가 없습니다. 이것은 버그 가능성도 낮아지고, 유지보수비용이 감소함을 뜻합니다.
심지어, SomeClass와 SomeClassArray가 다음과 같이 리스트로 바뀌는 등 구조가 완전히 바뀌더라도
class SomeClass
{
......
SomeClass *Next;
};
SomeClass *SomeClassArray; // 리스트구조의 첫항
만약 이렇게 바뀐다면, 일반적인 for루틴을 사용했을 경우는 다음과 같이 바뀌어야 합니다만,
SomeClass *k;
for(k = SomeClassArray; k != nullptr; k = k->Next)
k->Read();
for(k = SomeClassArray; k != nullptr; k = k->Next)
k->Process();
for(k = SomeClassArray; k != nullptr; k = k->Next)
k->Write();
for(k = SomeClassArray; k != nullptr; k = k->Next)
Func(k);
만약 iterator를 사용한다면
class SomeClassIterator // 반복자 정의
{
private :
SomeClass *SomeClassArray;
//int Size;
SomeClass *Finger;
public :
SomeClassIterator(SomeClass *arr, int size)
{
SomeClassArray = arr;
//Size = size;
Finger = arr;
}
~SomeClassIterator(void)
{
}
SomeClass *operator ->(void)
{
return Finger;
}
SomeClass *operator *(void)
{
return Finger;
}
void operator ++(void)
{
if(Finger != nullptr)
Finger = Finger->Next;
}
void Home(void)
{
Finger = SomeClassArray;
}
bool IsEnd(void)
{
return Finger == nullptr;
}
};
SomeClassIterator iter(SomeClassArray, 1024); // 반복자 선언
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Read();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Process();
for(iter.Home(); !iter.IsEnd(); ++iter)
iter->Write();
for(iter.Home(); !iter.IsEnd(); ++iter)
Func(*iter);
와 같이 역시 Iterator 부분만 고치는 것으로 끝납니다.
즉 iterator는 반복루틴 자체를 추상화함으로써 유지보수비용을 줄이는 기법입니다.
댓글 없음:
댓글 쓰기