2. 함수 포인터
2-1. 함수 포인터란
- 변수 : 값을 저장하는 메모리 공간의 이름
- 포인터 : 주소를 저장하는 메모리 공간의 이름
- 함수 포인터 : 함수의 시작 주소를 저장하는 포인터
void Print(int num)
{
cout << "값 : " << num << endl;
}
int main()
{
void (*pf)(int); // void(int num)이기 때문에 void(*이름)(int로) 선언
pf = Print; // 함수의 이름으로 시작 주소를 설정
pf(10); // 함수포인터 호출 1
(*pf)(10); // 함수포인터 호출 2
}
2-2. 함수 포인터의 종류
함수는 정적 함수(전역, namespace내 전역, static)와 멤버 함수로 나뉜다. 또한, 멤버함수는 객체와 주소로 호출하기 때문에 총 3가지로 나뉜다.
- 정적 함수 호출
- 객체로 멤버함수 호출
- 객체의 주소로 멤버 함수 호출
void Print()
{
cout << "정적 함수" << endl;
}
class Point()
{
public:
void Print()
{
cout << "멤버 함수" << endl;
}
}
int main()
{
Point pt;
Point *ptr &pt;
Print(); // 정적함수
pt.Print(); // 객체를 통한 멤버함수
ptr->Print(); // 주소를 통한 멤버함수
}
- 정적 함수 호출
정적함수는 전역 함수, namespace내의 전역함수, static 함수 모두 같은 규악으로 호출한다.
// 함수반환 (*이름)(타입)
void (*pf)(int);
void Print()
{
cout << "전역함수" << endl;
}
namespace A
{
void Print()
{
cout << "namespace내 전역함수" << endl;
}
}
class Point()
{
public:
static void Print()
{
cout << "클래스의 정적 멤버 함수" << endl;
}
}
int main()
{
void (*pf)(void);
Print(); // 전역함수
A::Print(); // namespace내 전역함수
Point::Print(); // 클래스의 정적 멤버 함수
pf = Print;
pf();
pf = A::Print;
pf();
pf = Point::Print;
pf();
}
- 객체와 주소로 멤버 함수 호출
멤버 함수 포인터는 함수 포인트 선언에 어ㅏ떤 클래스의 멤버 함수를 가리킬 것인지, 클래스를 선정해야한다.
- * 객체로 멤버함수 호출(.* 연산자) : (객체.*pf)(10)
- * 주소로 멤버함수 호출(->* 연산자) : (주소->*pf)(10)
class Point()
{
int x;
int y;
public:
explicit Point(int a=0, int b=0) : x(a), y(b) {}
void Print() const { cout << x << ',' << y << endl; }
void PrintInt(int n) const { cout << "정수 : " << n << endl; }
}
int main()
{
Point pt(2,3);
Point* ptr = &pt;
// 반환타입(클래스 이름::*포인터 함수 이름)(인수 타입)
void(Point::*pf1)() const;
void(Point::*pf2)(int) const;
// 함수포인터 = &클래스이름::멤버함수 이름
pf1 = &Point::Print;
pf2 = &Point::PrintInt;
// 객체 호출
(pt.*pf1)(); // pt.Print()
(pt.*pf1)(10); // pt.PrintInt(10)
// 주소 호출
(ptr->*pt2)(); // ptr->Print()
(ptr->*pt2)(10); // ptr->PrintInt(10)
}
2-3. 클라이언트 코드와 서버 코드
- 서버 코드 : 어떤 기능이나 서비스를 제공하는 코드 측
- 클라이언트 코드 : 기능을 제공 받는 코드 측
// 서버
void Print()
{
cout << "서버입니다" << endl;
}
// 클라이언트
int main()
{
Print(); // 클라이언트가 서버를 Call한다.
}
- 콜 : 클라이언트가 서버를 Call
- 콜백 : 서버가 클라이언트 Call
// 서버
void Print()
{
cout << "서버입니다" << endl;
Client(); // 클라이언트 호출!
}
// 클라이언트
void Client()
{
cout << "클라이언트입니다" << endl;
}
int main()
{
Print(); // 서버 호출!
return 0;
}
// 서버
void For_each(int *begin, int *end, void (*pf)(int))
{
while(begin != end)
{
pf(*begin++); // 클라이언트 함수 호출 (콜백)
}
cout << endl;
}
// 클라이언트
void Print1(int n)
{
cout << n << ' ';
}
void Print2(int n)
{
cout << n*10 << ' ';
}
void Print3(int n)
{
cout << "정수 : " << n << endl;
}
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
// 클라이언트는 서버 함수 Foreach를 3번 호출한다.
For_each(arr, arr+5, Print1);
For_each(arr, arr+5, Print2);
For_each(arr, arr+5, Print3);
// 1 2 3 4 5
// 10 20 30 40 50
// 정수 : 1
// ...
// 정수 : 5
}
※ STL의 for_each 알고리즘
#include <algorithm> // for_each 사용을 위한 헤더파일
int main()
{
for_each(arr, arr+5, Print();
}
'C++ STL > Part 01 C++ 문법' 카테고리의 다른 글
4장 템플릿 (0) | 2021.06.22 |
---|---|
3장 함수 객체 (0) | 2021.06.22 |
1장 연산자 오버로딩 (0) | 2021.06.17 |
댓글