C++ - 유저 정의 클래스에서 간단하게 확장 for 문을 사용할 수 있도록 하는 방법

출처

STL 컨테이너를 public 상속한 경우

유의해야 할 것은 STL 컨테이너의 소멸자는 virtual 이 아니다
예를 들면 부모 클래스의 포인터로 업 캐스트하고 delete 하면 자식 클래스의 소멸자가 호출되지 않는다.

코드 예

#include <iostream>
#include <vector>
using namespace std;

using VectReal = std::vector<double>;

class MyVect : public VectReal
{
public:
    MyVect(std::initializer_list<double> list)
        : VectReal(list)
    { }
};

int main(void)
{
    MyVect v = { 1, 2, 3, 4, 5 };
    for (double d : v) { cout << d << " "; }
}

콘솔 출력
1 2 3 4 5

STL 컨테이너를 private 상속한 경우

부모 클래스의 필요한 멤버를 using 선언을 추가한다.

코드 예

#include <iostream>
#include <vector>
using namespace std;

using VectReal = std::vector<double>;

class MyVect : private VectReal
{
public:
    /* 부모 클래스의 반복자를 사용하기 위해 iterator, const_iterator, begin, end 을 using 한다 */
    using VectReal::iterator;
    using VectReal::const_iterator;
    using VectReal::begin;
    using VectReal::end;
    // ...이 외 사용하고 싶은 메소드, 멤버, typedef 를 using 한다

    MyVect(std::initializer_list<double> list)
        : VectReal(list)
    { }
};

int main(void)
{
    MyVect v = { 1, 2, 3, 4, 5 };
    for (double d : v) { cout << d << " "; }
}

콘솔 출력
1 2 3 4 5

STL 컨테이너를 가진 경우

코드 예

#include <iostream>
#include <vector>
using namespace std;

using VectReal = std::vector<double>;

class MyVect
{
public:

    MyVect(std::initializer_list<double> list)
        : m_vect(list)
    { }

    // iterator, const_iterator의 typedef를 해 두면 MyVect::iterator 라고 쓸 수 있어서 편리하다(필수는 아니다)
    using iterator = VectReal::iterator;
    using const_iterator = VectReal::const_iterator;

    // m_vect 로 처리를 위임
    iterator begin() { return m_vect.begin(); }
    iterator end() { return m_vect.end(); }
    const_iterator begin() const { return m_vect.begin(); }
    const_iterator end() const { return m_vect.end(); }


private:
   // 멤버로 가진다
   VectReal m_vect;
};

int main(void)
{
    MyVect v = { 1, 2, 3, 4, 5 };
    for (double d : v) { cout << d << " "; }
}

콘솔 출력
1 2 3 4 5

포인터와 배열을 멤버로 가진 경우

① 포인터를 반복자로서 typedef 하고, ② begin, end를 아래처럼 구현한다
rbegin, rend 도 같은 요령으로 구현할 수 있다.

코드 예

#include <iostream>
#include <vector>
using namespace std;

class MyVect
{
public:

    MyVect(std::initializer_list<double> list)
    {
        m_size = list.size();
        m_vect = new double[m_size];
        std::copy(list.begin(), list.end(), m_vect);
    }

    using iterator = double*;
    using const_iterator = const double*;

    iterator begin() { return m_vect; }
    iterator end() { return m_vect + m_size; }
    const_iterator begin() const { return m_vect; }
    const_iterator end() const { return m_vect + m_size; }


private:
   double* m_vect;
   size_t m_size;
};

int main(void)
{
    MyVect v = { 1, 2, 3, 4, 5 };
    for (double d : v) { cout << d << " "; }
}

이 글은 2020-03-27에 작성되었습니다.