CharInfo info = *listiter; // 1
const CharInfo& info = *listiter; // 2
int a = 10;
++(++(++a));
++(++listiter);
int Add(int a, int b)
{
int c;
return c;
}
iterator* operator ++() // 1
{
assert(m_Owner && m_TargetNode);
m_TargetNode = m_TargetNode->pNext;
return *this; // 2
}
++(*(++listiter));
iterator& operator ++() // 1
{
assert(m_Owner && m_TargetNode);
m_TargetNode = m_TargetNode->pNext;
return *this; // 2
}
++(++(++listiter)); // 3
int i = 0;
int i2 = i++; // 1
int i2 = ++i; // 2
List<CharInfo>::iterator listiter2;
listiter = charlist.begin()
listiter2 = listiter;
listiter2 = ++listiter;
listiter++;
int Add(int, int);
int main()
{
return 0;
}
int Add(int c, int d)
{
return c + d;
}
iterator operator++(int) // 1
{
iterator copyiter;
copyiter = *this; // 2
++(*this); // 3
return copyiter; // 4
}
iterator& operator--()
{
assert(m_Owner && m_TargetNode);
assert(m_Owner->m_pHead != m_TargetNode); // iterator 가 begin 이다.
m_TargetNode = m_TargetNode->pPrev;
return *this;
}
Assertions:
assert(m_Owner && m_TargetNode)
: 이 assert 문은 m_Owner
와 m_TargetNode
가 둘 다 nullptr
이 아님을 확인합니다. 즉, 반복자가 유효한 컨테이너에 연결되어 있고, 타겟 노드가 존재한다는 것을 보장합니다.assert(m_Owner->m_pHead != m_TargetNode)
: 이 assert 문은 m_TargetNode
가 컨테이너의 첫 번째 노드(헤드)가 아님을 확인합니다. 이는 반복자가 컨테이너의 begin
위치에 있지 않음을 보증합니다. 만약 반복자가 begin
위치에 있으면, 이전 요소로 이동할 수 없기 때문입니다.Node Movement: m_TargetNode = m_TargetNode->pPrev;
이 라인은 반복자의 현재 타겟 노드를 그 노드의 이전 노드(pPrev
)로 업데이트합니다. 이는 반복자를 한 위치 뒤로 이동시킵니다.
Return Statement: return *this;
는 수정된 반복자의 참조를 반환합니다. 이를 통해 메소드 체인(method chaining)이나 다른 연산에 이 반복자를 바로 사용할 수 있습니다.
iterator operator --(int)
{
iterator copyiter;
copyiter = *this;
--(*this);
return copyiter;
}
iterator copyiter(*this);
iterator copyiter = (*this);
List<CharInfo> CharList;
CharList.push_back(CharInfo(L"Warrior", 100, 30, 50));
CharList.push_back(CharInfo(L"Archer", 80, 50, 40));
CharList.push_back(CharInfo(L"Wizzard", 50, 100, 20));
List<CharInfo>::iterator iter = CharList.begin();
iterator insert(iterator _targetIter, const T& _Data);
template<typename T>
typename List<T>::iterator List<T>::insert(iterator _targetIter, const T& _Data)
{
}
assert(_targetIter.m_Owner == this);
if (m_pHead == _targetIter.m_TargetNode)
{
push_front(_Data); // 1
return iterator(this, m_pHead); // 2
}
else
{
// 1
Node<T> pNewNode = new Node<T>(_Data, _targetIter.m_TargetNode, _targetIter.m_TargetNode->pPrev);
// 2
_targetIter.m_TargetNode->pPrev->pNext = pNewNode;
// 3
_targetIter.m_TargetNode->pPrev = pNewNode;
// 4
++m_CurCount;
// 5
return iterator(this, pNewNode);
}
iter = CharList.insert(iter, CharInfo(L"Theif", 60, 30, 100));
++iter;
iter = CharList.insert(iter, CharInfo(L"Theif", 60, 30, 100));
friend
클래스의 기본 개념접근 권한: friend
클래스는 다른 클래스의 private 및 protected 멤버에 접근할 수 있습니다. 이는 일반적으로 다른 클래스에서 불가능한 일입니다.
양방향이 아님: 클래스 A가 클래스 B를 friend
로 선언하면, A는 B의 private 및 protected 멤버에 접근할 수 있지만, B는 자동적으로 A의 private 및 protected 멤버에 접근할 수 없습니다. B도 A의 멤버에 접근하려면, B 역시 A를 friend
로 선언해야 합니다.
선언 위치: friend
선언은 클래스 내부에서 이루어집니다. 이 선언은 public, private, 또는 protected 영역 어디에 위치해도 상관없습니다. 접근성은 friend
선언의 위치에 영향을 받지 않습니다.
class ClassA
{
friend class ClassB; // ClassB는 ClassA의 friend
private:
int secretValue;
};
class ClassB
{
public:
void accessClassA(ClassA& a)
{
// ClassB는 ClassA의 private 멤버에 접근할 수 있습니다.
a.secretValue = 10;
}
};
ClassB
는 ClassA
의 friend
이므로 ClassB
내의 메소드는 ClassA
의 private 멤버 secretValue
에 접근할 수 있습니다. iterator erase(iterator _targetIter);
template<typename T>
typename List<T>::iterator List<T>::erase(iterator _targetIter)
{
// 데이터 카운트 감소
// _targetIter 가 가리키고 있는 노드(삭제할 노드)
// 삭제할 노드 이전노드의 Next 를 삭제할 노드 Next로 교체
// 삭제할 노드 다음 노드의 Prev를 삭제할 노드 Prev로 교체.
// 예외상황(삭제할 노드가 Head 이거나 Tail 인 경우)
// _targetIter 가 가리키고 있는 노드를 delete(동적할당 해제)
// 삭제된 노드의 다음을 가리키는 iterator을 반환해준다.
return iterator();
}
#include <iostream>
#include <vector>
using std::vector;
#include <list>
using std::list;
#include "List.h"
struct CharInfo
{
wchar_t szName[20];
int HP;
int MP;
int SP;
int MaxHP;
int MaxMP;
int MaxSP;
public:
void SetInfo(const wchar_t* _strName, int _HP, int _MP, int _SP)
{
wcscpy_s(szName, _strName);
HP = MaxHP = _HP;
MP = MaxMP = _MP;
SP = MaxSP = _SP;
}
CharInfo()
: HP(0), MP(0), SP(0)
, MaxHP(0), MaxMP(0), MaxSP(0)
{}
CharInfo(const wchar_t* _strName, int _HP, int _MP, int _SP)
: HP(0), MP(0), SP(0)
, MaxHP(0), MaxMP(0), MaxSP(0)
{
SetInfo(_strName, _HP, _MP, _SP);
}
~CharInfo()
{}
};
List<CharInfo> charlist;
//list<CharInfo> stdcharlist;
int main()
{
int a = 10;
++(++(++a));
//CharInfo(L"Warrior", 100, 30, 50) - 임시객체, 이름없는 지역변수
charlist.push_back(CharInfo(L"Warrior", 100, 30, 50));
charlist.push_back(CharInfo(L"Archer", 80, 50, 40));
charlist.push_back(CharInfo(L"Wizzard", 50, 100, 20));
List<CharInfo>::iterator listiter;
listiter = charlist.begin();
const CharInfo& info = *listiter;
// 자기자신을 반환하게 만들었기 때문에, 다시 ++ 함수를 재 호출 가능
++(++(++listiter));
// 후위 연산자
int i = 0;
int i2 = ++i;
List<CharInfo>::iterator listiter2;
listiter = charlist.begin();
listiter2 = listiter++;
// insert 함수 테스트
List<CharInfo> CharList;
CharList.push_back(CharInfo(L"Warrior", 100, 30, 50));
CharList.push_back(CharInfo(L"Archer", 80, 50, 40));
CharList.push_back(CharInfo(L"Wizzard", 50, 100, 20));
// Warrior 를 가리킴
List<CharInfo>::iterator iter = CharList.begin();
// Warrior 에 Theif 를 insert 함( 카운트 4, iter 는 theif 를 가리킴)
// iter = CharList.insert(iter, CharInfo(L"Theif", 60, 30, 100));
// Archer 가리킴
// 카운트 4, iter 는 theif 를 가리킴, W -> T -> A -> Wi
++iter;
iter = CharList.insert(iter, CharInfo(L"Theif", 60, 30, 100));
// erase 테스트
return 0;
}
#pragma once
#include <assert.h>
template<typename T>
struct Node
{
T Data;
Node<T>* pNext;
Node<T>* pPrev;
Node()
: Data()
, pNext(nullptr)
, pPrev(nullptr)
{}
Node(const T& _Data, Node<T>* _Next, Node<T>* _Prev)
: Data(_Data)
, pNext(_Next)
, pPrev(_Prev)
{}
};
template<typename T>
class List
{
private:
Node<T>* m_pHead;
Node<T>* m_pTail;
int m_CurCount;
public:
void push_back(const T& _Data);
void push_front(const T& _Data);
class iterator;
iterator begin() { return iterator(this, m_pHead); }
iterator end() { return iterator(this, nullptr); }
// _targetIter 가 가리키는곳에 _Data 를 저장시키고, 새로 저장한 데이터를 가리키는 iterator 를 반환해준다.
iterator insert(iterator _targetIter, const T& _Data);
// _targetIter 가 가리키는 데이터를 삭제하고, 삭제한 다음을 가리키는 iterator 를 반환
iterator erase(iterator _targetIter);
public:
List()
: m_pHead(nullptr)
, m_pTail(nullptr)
, m_CurCount(0)
{}
~List()
{
Node<T>* pNode = m_pHead;
while (pNode)
{
Node<T>* pNext = pNode->pNext;
delete pNode;
pNode = pNext;
}
}
public:
class iterator
{
private:
List<T>* m_Owner;
Node<T>* m_TargetNode;
public:
T& operator *()
{
// Owner(List) 가 설정되어있지 않으면, 정상적인 iterator 가 아니다.
// Owner 가 설정되어 있어도, m_TargetNode 가 nullptr 이면 End Iterator 이기 때문에
// 마지막의 다음을 가리키는 상태의 iterator 에게 * 로 접근기능을 쓰면 에러
assert(m_Owner && m_TargetNode);
return m_TargetNode->Data;
}
// 1. ++, -- 반환타입 문제
// 2. ++, -- 후위연산자 문제
iterator& operator ++()
{
// enditerator 에서 ++ 하는 경우
assert(m_Owner && m_TargetNode);
m_TargetNode = m_TargetNode->pNext;
return *this;
}
iterator operator++(int)
{
iterator copyiter = *this;
++(*this);
return copyiter;
}
iterator& operator --()
{
assert(m_Owner && m_TargetNode);
assert(m_Owner->m_pHead != m_TargetNode); // iterator 가 begin 이다.
m_TargetNode = m_TargetNode->pPrev;
return *this;
}
iterator operator --(int)
{
iterator copyiter = *this;
++(*this);
return copyiter;
}
bool operator == (const iterator& _otheriter)
{
if (m_Owner == _otheriter.m_Owner && m_TargetNode == _otheriter.m_TargetNode)
return true;
else
return false;
}
bool operator != (const iterator& _otheriter)
{
return !((*this) == _otheriter);
}
public:
iterator()
: m_Owner(nullptr)
, m_TargetNode(nullptr)
{}
iterator(List<T>* _Owner, Node<T>* _TargetNode)
: m_Owner(_Owner)
, m_TargetNode(_TargetNode)
{}
~iterator()
{}
friend class List<T>;
};
};
template<typename T>
void List<T>::push_back(const T& _Data)
{
Node<T>* pNewNode = new Node<T>(_Data, nullptr, nullptr);
if (0 == m_CurCount) //nullptr == m_pHead)
{
m_pHead = pNewNode;
m_pTail = pNewNode;
}
else
{
m_pTail->pNext = pNewNode;
pNewNode->pPrev = m_pTail;
m_pTail = pNewNode;
}
++m_CurCount;
}
template<typename T>
inline void List<T>::push_front(const T& _Data)
{
Node<T>* pNewNode = new Node<T>(_Data, m_pHead, nullptr);
if (nullptr != m_pHead)
{
m_pHead->pPrev = pNewNode;
}
else
{
m_pTail = pNewNode;
}
m_pHead = pNewNode;
++m_CurCount;
}
template<typename T>
typename List<T>::iterator List<T>::insert(iterator _targetIter, const T& _Data)
{
assert(_targetIter.m_Owner == this);
if (m_pHead == _targetIter.m_TargetNode)
{
push_front(_Data);
return iterator(this, m_pHead);
}
else
{
Node<T>* pNewNode = new Node<T>(_Data, _targetIter.m_TargetNode, _targetIter.m_TargetNode->pPrev);
_targetIter.m_TargetNode->pPrev->pNext = pNewNode;
_targetIter.m_TargetNode->pPrev = pNewNode;
++m_CurCount;
return iterator(this, pNewNode);
}
}
template<typename T>
typename List<T>::iterator List<T>::erase(iterator _targetIter)
{
return iterator();
}
1차 24.01.02
2차 24.01.03
3차 24.01.04
4차 24.01.05
5차 24.01.09