함수 포인터

seio·2022년 9월 18일
0

C++ STL

목록 보기
2/17

함수 포인터란?

변수는 값을 저장하는 메모리 공간의 이름이다.
포인터는 주소를 저장하는 메모리 공간의 이름이다.
함수 포인터는 함수의 시작 주소를 저장하는 포인터이다.

함수의 이름은 함수가 시작하는 시작 주소이며, 함수 포인터는 이 함수의 주소를 저장하는 포인터입니다. 함수 포인터는 함수 시그니처(signature: 함수의 반환 타입과 매개변수 리스트)와 같게 선언합니다.

예를 들어 시그니처가 갖는 int func(int a, int b)인 함수의 함수 포인터는
int (*pf)(int,int)로 선언한다.

void print(int n){
cout<< n <<endl;
}

int main(){

void (*fp)(int);
fp = print;

print(10); // 1. 함수 호출
fp(10);    // 2. 포인터를 이용한 함수호출
(*fp)(10); // 3. 포인터를 이용한 함수호출

// print == pf == *pf 가 모두 같은 주소 값을 갖는다.
}

함수의 이름인 print가 함수의 시작 주소이므로 fp도 함수의 시작 주소이며, 함수 호출은 함수 포인터를 이용해 'fp()'처럼 호출한다.

또한, 함수 포인터는 메모리 접근 연산자()를 붙여도 함수의 주소이다. 그래서 fp와 fp는 print() 함수의 주소이며 fp()나 (*fp)()는 같은 문장이다.

함수 포인터의 종류

c++에서 함수는 정적(static) 함수와 멤버 함수로 나눌 수 있다.

여기서 정적 함수로는 전역 함수, namespace 내의 전역 함수, static 멤버 함수가 해당된다.
멤버 함수는 다시 객체와 주소로 각각 호출할 수 있으므로 함수 호출은 세 가지가 있다.

  • 1) 정적 함수 호출(정적함수)
  • 2) 객체로 멤버 함수 호출 (멤버 함수)
  • 3) 객체의 주소로 멤버 함수 호출 (멤버 함수)
void print(int a){ cout<<a<<endl;}

class point{
public:
void print(){cout<<endl;}
};

main(){
	point pt;
    point* p = &pt;
    
    print(10);  //정적 함수 호출
    pt.print(); // 객체로 멤버 함수 호출
    p->print(); // 주소로 멤버 함수 호출
}

정적 함수 호출

정적 함수 포인터는 함수 시그니처만 알면 쉽게 선언할 수 있다.
정적 함수인 전역 함수, namespace내의 전역 함수, static 멤버 함수는 모두 함수 호출 규약이 같아서 함수 포인터가 같다.

void print(){};
namespace A
{
	void print(){}
}
class pt{
	public:	
    	static void print(){}
};

main(){
void (*fp)();

//함수 호출하여 출력
print();
A::print();
pt::print();

//함수 포인터 사용

fp = print;
fp();

fp = A::print;
fp();

fp = pt::print;
fp();
}

객체와 주소로 멤버 함수 호출

멤버 함수 포인터는 함수 푄터 선언에 어떤 클래스의 멤버 함수를 가르킬 것인지 클래스 이름을 지정해야합니다.

시그니처가 void point::print(int n)인 멤버 함수의 포인터는 void (point::*pf)(int)처럼 선언한다.

    • 객체로 멤버 함수 호출 시에는 . 연산자를 이용한다.
      ex) (객체.*fp)(10)
    • 주소로 멤버 함수 호출 시에는 -> 연산자를 이용한다.
      ex) (주소->*fp)(10)
class point{
	public:
    explicit point(~~){}
    void print const(){}
    void printint(int n) {};
}

main{
	point pt(2, 3);
    point* p = &pt;
    
    void (point::*fp1)() const;
    fp1 = &point::print;
   
    void (point::*fp2)(int);
    fp2 = &point::printint;

	pt.print();
    pt.printint(10);

	// 객체로 멤버 함수 포인터를 이용한 호출
	(pt.*fp1)();
    (pt.*fp2)(10);
    
    // 주소로 멤버 함수 포인터를 이용한 호출
    (p->*fp1)();
    (p->*fp2)(10);

}

for each 예시

//서버
void for_each(int *begin, int* end, void (*print)(int))
{
	while(begin!=end){
    	print(*begin++); //클라이언트 함수 호출(콜백)
    }
}

//클라이언트
void print1(int n){
	cout<<n<<endl;
}
void print2(int n){
	cout<<n*n<<endl;
}
void print3(int n){
	cout<<1<<endl;
}

main(){

int arr[5] = {10, 20, 30, 40, 50};

for_each(arr, arr+5, print1);
for_each(arr, arr+5, print2);
for_each(arr, arr+5, print3);
}
profile
personal study area

0개의 댓글