함수 개체, 회원 및 회원 컬렉션 구현[C++]

안녕하세요. 언제나 휴일에 언휴예요.

이번에는 함수 개체 실습이예요.

함수 개체는 특정 형식 개체를 함수처럼 호출 가능한 개체를 말합니다.

이를 위해 해당 형식에는 함수 호출 연산자를 중복 정의합니다.

이 외에도 이번 실습에는 개체 출력자, 인덱스 연산자 중복 정의를 구현하는 부분도 있습니다.

다음은 함수 호출 연산자를 중복 정의한 간단한 예제입니다.

class FunObject
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};
int main()
{
    FunObject fobj;
    int re = fobj(3,4);
    cout << "결과:" << re << endl;
    return 0;
}

위 예에서 FunObject 클래스에는 함수 호출 연산자를 중복 정의하고 있습니다.

그리고 FunObject 형식 변수 fobj 를 함수 처럼 호출하는 것을 볼 수 있습니다.

이번 실습에서는 회원 클래스를 정의하고 회원 클래스를 보관하는 회원 컬렉션을 구현할 거예요.

회원 컬렉션 형식에는 특정 조건을 만족하는 회원 개체를 반환하는 메서드(FindIf)를 제공할 거예요.

그리고 해당 메서드의 입력 인자로 특정 조건을 만족하는지 판별하는 알고리즘을 정의한 함수 개체를 전달 받을 거예요.

다음은 실습 소스 코드입니다.

/* https://ehpub.co.kr
   C++ 예제 - 언제나 휴일
   함수 개체 - 회원 컬렉션
   연산자 중복 정의 및 개체 출력자 포함
*/
#include 
#include 
using namespace std;

class Member
{
    int num;
    string name;
public:
    Member(int num, string name)
    {
        this->num = num;
        this->name = name;
    }
    int GetNum()const
    {
        return num;
    }
    string GetName()const
    {
        return name;
    }
};

ostream& operator<<(ostream& os, const Member* data)
{
    os << "번호:" << data->GetNum() << " 이름:" << data->GetName();
    return os;
}

class IEqual
{
public:
    virtual bool operator()(Member* data) = 0;
};

class MemberCollection
{
    Member** base;
    const int capacity;
    int count;
public:
    MemberCollection(int capacity) :capacity(capacity)
    {
        base = new Member * [capacity];
        count = 0;
    }
    ~MemberCollection()
    {
        delete[] base;
    }
    bool PushBack(Member* data)
    {
        if (IsFull())
        {
            return false;
        }
        base[count] = data;
        count++;
        return true;
    }
    bool IsFull()const
    {
        return count == capacity;
    }
    bool IsAvailIndex(int index)const
    {
        return (index >= 0) && (index < capacity);
    }
    int GetCount()const
    {
        return count;
    }
    Member*& operator[](int index)
    {
        if (IsAvailIndex(index) == false)
        {
            throw "사용할 수 없는 인덱스";
        }
        return base[index];
    }
    Member* FindIf(IEqual& ie)
    {
        for (int i = 0; i < count; i++)
        {
            if (ie(base[i]))
            {
                return base[i];
            }
        }
        return NULL;
    }
};


class EqualNum :
    public IEqual
{
    int num;
public:
    EqualNum(int num)
    {
        this->num = num;
    }
    virtual bool operator()(Member* data)
    {
        return num == data->GetNum();
    }
};

int main()
{
    MemberCollection dc(100);
    dc.PushBack(new Member(3, "홍길동"));
    dc.PushBack(new Member(2, "강감찬"));
    dc.PushBack(new Member(6, "을지문덕"));
    dc.PushBack(new Member(7, "한석봉"));

    int count = dc.GetCount();
    for (int i = 0; i < count; i++)
    {
        cout << dc[i] << endl;
    }

    cout << "검색할 회원 번호:";
    int num;
    cin >> num;
    EqualNum en(num);
    Member* member = dc.FindIf(en);
    if (member != NULL)
    {
        cout << member << endl;
    }
    else
    {
        cout << "찾지 못하였음" << endl;
    }

    for (int i = 0; i < count; i++)
    {
        delete dc[i];
    }

    return 0;
}