기존에는 커스텀예외객체만을 생성해놓고 try, catch는 모두 자료구조의 함수 안에서 실행하도록 했지만, 이젠 try catch를 호출하는 static 클래스를 만든 뒤, 자료구조에선 해당 함수를 호출하도록 하였다.

 

#pragma once
#include <cassert>
#include "CustomException.h"

enum class ExceptionType
{
    OutOfRange,
    EmptyContainer,
};

class ExceptionFunction
{
public:
    static void CheckException(bool _IsOccurred, bool _DoAssert, const char* _ClassName, ExceptionType _ExceptionType)
    {
        try
        {
            if (_IsOccurred == true)
            {
                ThrowException(_ClassName, _ExceptionType);
            }
        }
        catch (std::exception& _Error)
        {
            std::cerr << _Error.what() << std::endl;
            assert(_DoAssert);
        }
    }

private:
    static void ThrowException(const char* _ClassName, ExceptionType _ExceptionType)
    {
        switch (_ExceptionType)
        {
        case ExceptionType::OutOfRange:
            throw CustomException::OutOfLange(_ClassName);
            break;
        case ExceptionType::EmptyContainer:
            throw CustomException::EmptyContainer(_ClassName);
            break;
        }
    }
};

 

이렇게, 외부에선 CheckException 함수를 호출하여 파라미터를 잘 대입해준다면, 예외 발생 여부를 검사하고 그에 맞는 메세지를 출력하고 예외 객체를 던지고 assert하는 것까지 모두 해당 함수 내부에서 처리하도록 하였다.

virtual const bool& At(size_t _Index) 
{	
    try
    {
        if (_Index >= MySize)
        {
            throw CustomException::OutOfLange();
        }
    }
    catch (std::exception& _Error)
    {
        std::cerr << _Error.what() << std::endl;
        assert(false);
    }

    return MyElements[_Index];
}

위는 기존의 At 코드인데, 이 코드는 아래와 같이 바뀌었다.

virtual const bool& At(size_t _Index) 
{
    ExceptionFunction::CheckException(_Index >= MySize, true, typeid(*this).name(), ExceptionType::OutOfRange);
    return MyElements[_Index];
}

그리고, List도 일부 기능을 구현하였다.

먼저, List클래스 내부에서만 사용할 수 있는 Node 중첩 클래스를 선언하였고, 이를 통해 원소들이 연결되도록 하였다.

 

List는 Head와 Tail을 보유하고 있고, 더미노드를 생성하여 각각 더미노드를 가리키도록 하였다.

즉 List의 가장 앞의 원소는 Head의 다음 원소가 되는 셈이며, 가장 뒤의 원소는 Tail의 앞의 원소가 되는 것이다.

 

아래는 구현된 코드 전문이다.

#pragma once
#include "ExceptionFunction.h"

template <typename DataType>
class List
{
    class Node;
public:
    List()
    {
        CreateDummyNode();
    }

    List(size_t _Size)
    {
        CreateDummyNode();
        
        for (int i = 0; i < _Size; i++)
        {
            Push_Back(DataType());
        }
    }

    List(size_t _Size, const DataType& _Data)
    {
        CreateDummyNode();

        for (int i = 0; i < _Size; i++)
        {
            Push_Back(_Data);
        }
    }

    List(size_t _Size, DataType&& _Data)
    {
        CreateDummyNode();

        for (int i = 0; i < _Size; i++)
        {
            Push_Back(_Data);
        }
    }

public:
    void Push_Back(const DataType& _Data)
    {
        Node* NewNode = new Node();
        NewNode->DataPtr = _Data;

        Node* CurBackNode = Tail->PrevNode;
        CurBackNode->NextNode = NewNode;

        NewNode->PrevNode = CurBackNode;
        NewNode->NextNode = Tail;

        Tail->PrevNode = NewNode;

        MySize++;
    }

    void Push_Back(DataType&& _Data)
    {
        Node* NewNode = new Node();
        NewNode->DataPtr = _Data;

        Node* CurBackNode = Tail->PrevNode;
        CurBackNode->NextNode = NewNode;

        NewNode->PrevNode = CurBackNode;
        NewNode->NextNode = Tail;

        Tail->PrevNode = NewNode;

        MySize++;
    }

    const DataType& Front()
    {
        ExceptionFunction::CheckException(Head->NextNode == nullptr, true, typeid(*this).name(), ExceptionType::OutOfRange);
        return Head->NextNode->DataPtr;
    }

    const DataType& Back()
    {
        ExceptionFunction::CheckException(Tail->PrevNode == nullptr, true, typeid(*this).name(), ExceptionType::OutOfRange);
        return Tail->PrevNode->DataPtr;
    }

private:
    class Node
    {
    public:
        void operator=(const Node* _Node)
        {
            DataPtr = _Node->DataPtr;
            PrevNode = _Node->PrevNode;
            NextNode = _Node->NextNode;
        }

        const Node* operator++()
        {
            *this = NextNode;
            return *this;
        }

        const Node operator++(int)
        {
            Node ReturnNode = NextNode;
            ++(*this);
            return ReturnNode;
        }

        const Node* operator--()
        {
            *this = PrevNode;
            return *this;
        }

        const Node* operator--(int)
        {
            Node ReturnNode = PrevNode;
            --(*this);
            return ReturnNode;
        }

        DataType* DataPtr = nullptr;
        Node* PrevNode = nullptr;
        Node* NextNode = nullptr;
    };

private:
    void CreateDummyNode()
    {
        Node* DummyHead = new Node();
        Node* DummyTail = new Node();

        Head = DummyHead;
        Tail = DummyTail;

        DummyTail->PrevNode = Head;
        DummyHead->NextNode = Tail;
    }

private:
    Node* Head = nullptr;
    Node* Tail = nullptr;
    
    size_t MySize = 0;
};

 

+ Recent posts