이번에는 함수 호출 연산자 중복 정의와 함수 개체를 알아보기로 해요.
C++언어에서는 함수 호출 연산자를 중복정의 할 수 있습니다. 함수 호출 연산자의 연산 기호는 ( ) 입니다. 따라서 함수 호출 연산자를 중복 정의할 때 메서드 이름은 operator()입니다. 메서드 뒤에 입력 매개 변수 리스트를 열거하는 ()에는 개발자가 개수와 형식을 결정하고 반환 형식도 개발자가 정합니다.
[반환형식] operator() ([입력 매개 변수 리스트]);
그리고 함수 호출 연산자를 중복 정의한 형식의 개체를 함수 개체라고 부릅니다. 함수 개체는 형식 내부에 함수 호출 연산자를 중복 정의하고 있어서 마치 함수처럼 호출하여 사용할 수 있습니다.
먼저 간단하게 함수 호출 연산자 중복 정의를 사용하여 함수 개체를 함수처럼 사용하는 예를 보여드를게요.
//함수 호출 연산자 중복 정의 #include <iostream> using namespace std; class FunClass { public: int operator()(int a,int b)//함수 호출 연산자 중복 정의 { cout<<"테스트"<<endl; return a*b; } }; int main() { FunClass fc;//함수 개체 cout<<fc(3,4)<<endl;//함수 개체를 함수처럼 사용 return 0; }
▷ 실행 결과
테스트
12
보통 함수 개체는 메서드를 구현하는 곳에서 모든 알고리즘을 정의하지 못하고 일부를 호출하는 곳에서 정의한 알고리즘을 이용할 때 사용합니다. 예를 들어 회원을 보관하는 배열을 구현하면서 검색 기능을 구현할 때 호출하는 곳에서 검색 기능을 구현한 함수 개체를 입력 인자로 받아 이를 이용하는 것이죠. 또한 배열에 보관한 회원 정보를 출력하는 알고리즘을 호출하는 곳에서 함수 개체로 전달받아 이를 이용하여 출력하게 할 수도 있겠죠. 마찬가지로 배열에 보관한 회원 정보를 정렬할 때 비교 알고리즘을 함수 개체를 입력 인자로 전달받아 이용할 수도 있을 거예요.
다음처럼 배열에서는 함수 호출 연산자를 중복 정의한 알고리즘을 추상화합니다.
#define interface struct interface IEqual { virtual bool operator()(Member *member)=0; };
그리고 배열의 검색 기능에서는 함수 개체를 입력 인자로 받아 조건에 맞는 것을 구현하죠.
Member *MemberCollection::FindIf(IEqual &ie) { for(int i=0;i<usage;i++) { if(ie(base[i])) { return base[i]; } } return 0; }
사용하는 곳에서는 검색에 필요한 알고리즘을 구체적으로 구현합니다.
class EqualerNum:public IEqual { int num; public: EqualerNum(int num) { this->num = num; } virtual bool operator()(Member *member) { return num == member->GetNum(); } };
그리고 배열의 검색 요청 시에 구체적으로 구현한 함수 개체를 입력 인자로 전달하여 원하는 것을 찾습니다.
MemberCollection mc(10); ...중략... EqualerNum en(3); Member *member = mc.FindIf(en); if(member==0) { cout<<"검색 실패"<<endl; } else { cout<<"번호:"<<member->GetNum()<<" 이름:"<<member->GetName()<<endl; }
다음은 함수 개체를 이용하여 회원 컬렉션을 정의하고 이를 이용하는 예제 코드입니다.
//Member.h #pragma once #include <iostream> #include <string> using namespace std; class Member { const int num; string name; public: Member(int num,string name); int GetNum()const; //회원 번호 접근자 string GetName()const; //회원 이름 접근자 };
//Member.cpp #include "Member.h" Member::Member(int num,string name):num(num) { this->name = name; } int Member::GetNum()const { return num; } string Member::GetName()const { return name; }
//MemberCollection.h #pragma once #include "Member.h" #define interface struct interface IEqual//조건 알고리즘 추상화 { virtual bool operator()(Member *member)=0; }; interface IDoSome //회원에 관한 알고리즘 추상화 { virtual void operator() (Member *member)=0; }; interface ICompare//회원 비교 알고리즘 추상화 { virtual int operator()(Member *m1,Member *m2)=0; }; class MemberCollection { Member **base; const int max_member; int usage; public: MemberCollection(int max); ~MemberCollection(void); void PushBack(Member *member);//순차 보관 Member *FindIf(IEqual &ie); //조건에 맞는 개체 탐색 void ListMember(IDoSome &iv); //전체 회원 데이터에 알고리즘 적용 void Sort(ICompare &ic); //검색 알고리즘 이용하여 정렬 };
//MemberCollection.cpp #include "MemberCollection.h" MemberCollection::MemberCollection(int max):max_member(max) { base = 0; if(max) { base = new Member *[max]; } usage = 0; } MemberCollection::~MemberCollection(void) { if(base) { delete[] base; } } void MemberCollection::PushBack(Member *member) { if(usage<max_member) { base[usage] = member; usage++; } } Member *MemberCollection::FindIf(IEqual &ie) { for(int i=0;i<usage;i++) { if(ie(base[i])) //조건 알고리즘을 사용 { return base[i]; } } return 0; } void MemberCollection::ListMember(IDoSome &iv) { for(int i=0;i<usage;i++) { iv(base[i]);//회원에 관한 알고리즘 사용 } } void MemberCollection::Sort(ICompare &ic) { for(int i=usage;i>1;i--) { for(int j=1;j<i;j++) { if(ic(base[j-1],base[j])>0) //비교 알고리즘 사용 { Member *temp = base[j-1]; base[j-1] = base[j]; base[j]=temp; } } } }
//Program.cpp #include "MemberCollection.h" class EqualerNum:public IEqual //번호로 비교 알고리즘 { int num; public: EqualerNum(int num) { this->num = num; } virtual bool operator()(Member *member) { return num == member->GetNum(); } }; class ViewMember:public IDoSome//회원 출력 알고리즘 { public: virtual void operator() (Member *member) { cout<<"번호:"<<member->GetNum()<<" 이름:"<<member->GetName()<<endl; } }; class ViewMember2:public IDoSome//회원 출력 알고리즘2 { public: virtual void operator() (Member *member) { cout<<"이름:"<<member->GetName()<<" 번호:"<<member->GetNum()<<endl; } }; class Dispose:public IDoSome////회원에 관한 소멸 알고리즘 { public: virtual void operator() (Member *member) { delete member; } }; class CompareByNum:public ICompare//번호로 비교 알고리즘 { public: virtual int operator()(Member *m1,Member *m2) { return m1->GetNum()-m2->GetNum(); } }; class CompareByName:public ICompare//이름으로 비교 알고리즘 { public: virtual int operator()(Member *m1,Member *m2) { string s1 = m1->GetName(); string s2 = m2->GetName(); return s1.compare(s2); } }; int main() { MemberCollection mc(10); mc.PushBack(new Member(5,"이순신")); mc.PushBack(new Member(3,"홍길동")); mc.PushBack(new Member(1,"강감찬")); EqualerNum en(3);//번호로 검색 알고리즘 함수 개체 Member *member = mc.FindIf(en);//입력 인자로 함수 개체 전달 if(member==0) { cout<<"검색 실패"<<endl; } else { cout<<"번호:"<<member->GetNum()<<" 이름:"<<member->GetName()<<endl; } cout<<"전체 출력1"<<endl; ViewMember vm;//회원 출력 알고리즘 함수 개체 mc.ListMember(vm);//입력 인자로 함수 개체 전달 cout<<"전체 출력2"<<endl; ViewMember2 vm2;//회원 출력 알고리즘2 함수 개체 mc.ListMember(vm2);//입력 인자로 함수 개체 전달 cout<<"번호로 정렬 후 출력"<<endl; CompareByNum cbnum;//번호로 비교 알고리즘 함수 개체 mc.Sort(cbnum);//입력 인자로 함수 개체 전달 mc.ListMember(vm);//입력 인자로 함수 개체 전달 cout<<"이름으로 정렬 후 출력"<<endl; CompareByName cbname;//이름으로 비교 알고리즘 함수 개체 mc.Sort(cbname);//입력 인자로 함수 개체 전달 mc.ListMember(vm2);//입력 인자로 함수 개체 전달 Dispose dispose;//소멸 알고리즘 함수 개체 mc.ListMember(dispose);//입력 인자로 함수 개체 전달 return 0; }
▷ 실행 결과
번호:3 이름:홍길동
전체 출력1
번호:5 이름:이순신
번호:3 이름:홍길동
번호:1 이름:강감찬
전체 출력2
이름:이순신 번호:5
이름:홍길동 번호:3
이름:강감찬 번호:1
번호로 정렬 후 출력
번호:1 이름:강감찬
번호:3 이름:홍길동
번호:5 이름:이순신
이름으로 정렬 후 출력
이름:강감찬 번호:1
이름:이순신 번호:5
이름:홍길동 번호:3