iterator (2)

Yama·2023년 12월 27일
0

어소트락 수업

목록 보기
28/55

포함 클래스(Inner Class)

class MyClass
{
private:
	int m_i;
public:
	class Inner // 1
	{
	private:
		float m_f;
	};
};

int main()
{
	int size = 0;

	MyClass c;
	size = sizeof(MyClass);	// 2

	MyClass::Inner in;
	size = sizeof(MyClass::Inner);	 // 3
    
    return 0;
}
  • 포함 클래스의 특징
    • 포함 클래스가 선언된 클래스(MyClass)의 private까지 접근할 수 있다.
  • MyClass랑 Inner 클래스는 완전 별개의 자료형인데 하필 Inner가 MyClass안에 있는것이다.
    • MyClass를 네임스페이스로 생각하면 편하다.
  • 그래서 2번의 크기는 8바이트가 아니라 4바이트다.
  • 3번또한 그래서 4바이트다.

포함 클래스 사용하는 이유

  1. 반복자가 접근하려는 데이터를 관리하는 컨테이너의 private에 손쉽게 접근 가능하다
  2. 컨테이너 구분없이 동일한 이름을 가져서 반복자 역할 클래스의 이름을 손쉽게 알 수 있게 통일 시킴
    • Inner 클래스가 선언된 컨테이너 클래스가 각각 다르기 때문에 이름 중복문제가 발생하지 않는다.

iterator begin()함수 구현.

main.cpp

int main()
{
	 CArr<float>::iterator iter;

	// 2.4
	CArr<float> arrFloat;
	arrFloat.push_back(1.f);
	arrFloat.push_back(2.f);

	CArr<float>::iterator iter;
	iter = arrFloat.begin();

	return 0;
}

CArr.h

	class iterator
	{
	private:				
		CArr<T>*	m_pOwner;		// 1
		int			m_Idx;			// 1

	public:
		iterator()				
			: m_pOwner(nullptr)
			, m_Idx(-1)				// 2
		{
		}

		iterator(CArr<T>* _Owner, int _idx)	// 3
			: m_pOwner(_Owner)
			, m_Idx(_idx)	
		{}

		~iterator()
		{
		}

		
	};	
};
  • 1번은 실질적인 메모리 주소보다 누구를 관리자를 알고 잇으면 된다. T가 정해졌을떄의 관리자 소유주를 알고 있어야한다.
    • 그래서 맴버 변수는 2개.
  • 2번은 0이 안된다 0은 첫번째라는 뜻이라
    • 임의로 -1(마음대로 준값)을 초기값으로 준것이다 인덱스에 음수가 올 수는 없을떄니까 음수를 초기값으로 줌으로써 아무것도 안가르키고 있다는걸 표현함.
public:
	void push_back(const T& _Data);
	
	class iterator;					// 3
	iterator begin()				// 4
	{	
    	//iterator iter;			// 5
		//iter.m_pOwner = this;		// 5
		//iter.m_Idx = 0;			// 5
        
		iterator iter(this, 0);		// 6	
		return iter;
	}
  • 3번은 전방선언을 해서 iterator 클래스가 잇다고 알려줌.
  • 4번은 시작 관리자
  • 5번은 처음을 접근할떄 vecShort.begin()에서의 this가 나를 호출해서. 첫번째 접근해서 인덱스 0을 알려주는 것이다.
    • CArr은 내부 클래스에 private영역을 접근 못하기 떄문이다.
    • 이너 클래스는 본체에 프라이빗에 접근할수 잇지만 본체는 이너 클래스의 프라이빗에 접근할수 없기떄문이다.
  • _oWner 포인터랑, 인덱스를 입력을 해주면 입력된 두개로 각각 자기 맴버를 초기화 해주는 생성자 하나만 있었으면 해결된다.
    • 6번은 5번이 오류가 나서 접근하는 접근하는 인자를 this와 0을 넣었을떄 생성자를 3번처럼 구현을 해놔서 오류를 지웠다.

begin함수 구동 방식.

  1. 컨테이너는 iterator를 생성할 수 있는 begin 함수를 제공합니다.
  2. begin 함수는 컨테이너의 첫 번째 데이터를 가리키는 iterator를 생성하고 반환합니다.
  3. iterator는 이렇게 생성된 첫 번째 데이터를 가리키는 상태가 됩니다.
  4. begin 함수의 반환 타입은 iterator입니다.
  5. 동적 배열과 같은 컨테이너에서 begin 함수는 컨테이너 자체의 멤버 함수로 구현되며, 반환되는 것은 해당 컨테이너의 첫 번째 데이터를 가리키는 iterator입니다.
  6. 따라서 begin 함수의 반환값, 즉 iterator는 iterator 클래스의 인스턴스이며, 이 iterator를 사용하여 컨테이너의 데이터를 순회하거나 조작할 수 있습니다.
  • 요약
    • 간단히 말하면, begin 함수는 컨테이너의 시작 위치를 가리키는 iterator를 생성하고 이 iterator를 반환하며, 이 iterator를 통해 컨테이너의 데이터에 접근할 수 있습니다.
  • 참고
    • 인스턴스: 객체 지향 프로그래밍에서 객체를 생성한 것을 의미합니다. 이 문맥에서 "인스턴스"는 이터레이터 클래스의 객체를 나타냅니다.

강의 코드

main.cpp

#include <iostream>

#include "CArr.h"

#include <vector>
using std::vector;

class MyClass
{
private:
	int	m_i;

public:
	class Inner
	{
	private:
		float m_f;
	};
};

int main()
{
	int size = 0;

	MyClass c;
	size = sizeof(MyClass);

	MyClass::Inner in;
	size = sizeof(MyClass::Inner);


	CArr<float> arrFloat;
	arrFloat.push_back(1.f);
	arrFloat.push_back(2.f);

	CArr<float>::iterator iter;
	iter = arrFloat.begin();


	return 0;
}

CArr.h

#pragma once


// 클래스 템플릿
template<typename T>
class CArr
{
private:
	T*		m_pData;
	int		m_MaxCount;
	int		m_CurCount;

public:
	void push_back(const T& _Data);

	class iterator;
	iterator begin()
	{
		iterator iter(this, 0);
		return iter;
	}


private:
	void Realloc();

public:
	int size() { return m_CurCount; }
	int capacity() { return m_MaxCount; }
	T at(int _Idx) { return m_pData[_Idx]; }

	T& operator[](int _Idx) { return m_pData[_Idx]; }


public:
	CArr();
	~CArr();

	class iterator
	{
	private:
		CArr<T>*	m_pOwner;
		int			m_Idx;

	public:
		iterator()
			: m_pOwner(nullptr)
			, m_Idx(-1)
		{
		}

		iterator(CArr<T>* _Owner, int _idx)
			: m_pOwner(_Owner)
			, m_Idx(_idx)
		{}

		~iterator()
		{
		}
	};
};

template<typename T>
CArr<T>::CArr()
	: m_pData(nullptr)
	, m_CurCount(0)
	, m_MaxCount(2)
{
	m_pData = new T[m_MaxCount];
}

template<typename T>
CArr<T>::~CArr()
{
	delete[] m_pData;
}

template<typename T>
void CArr<T>::push_back(const T& _Data)
{
	if (m_MaxCount <= m_CurCount)
	{
		Realloc();
	}

	m_pData[m_CurCount++] = _Data;
}

template<typename T>
void CArr<T>::Realloc()
{
	m_MaxCount *= 2;
	T* pNew = new T[m_MaxCount];

	for (int i = 0; i < m_CurCount; ++i)
	{
		pNew[i] = m_pData[i];
	}

	delete[] m_pData;

	m_pData = pNew;
}

1차 23.12.27
2차 23.12.28
3차 23.12.29
4차 24.01.02
5차 24.01.03

0개의 댓글