728x90
선언방법
int (*pfunc1)(int, int); // 일반적인 방법
typedef int (*pfunc2)(int, int); // 편의를 위해 typdef를 이용하여 별칭을 정의
using pfunc3 = int(*)(int, int); // 편의를 위해 using을 이용하여 별칭을 정의
정의
함수 이름은 배열이름과 같ㅌ이 함수의 위치를 가리키는 주소값을 나타낸다. (실제론 &를 사용해서 함수를 참고해야 하는 경우도 있으니 절대적이진 않다.)
따라서 함수포인터 변수를 통해 동일한 시그니처의 함수를 전달할 수 있다.
사용법
- 1. 함수 포인터 변수 = [함수이름]
- 2. 함수 포인터 변수 = &[함수이름]
- 1. 함수이름();
- 2. (*함수이름)();
#include <iostream>
int func(int a, int b)
{
return a + b;
}
int main()
{
int (*pfunc)(int, int);
pfunc = func; // 방식1.배열이름과 같이 함수이름이 주소값을 나타낸다. 하지만 이는 C언어와의 호환성 때문에 컴파일러에서 지원 하는 기능이다.
pfunc = &func; // 방식2. 위 방식보다 이게 FM 방식이다. 클래스 멤버함수를 변수에 전달할 때는 FM 방식을 따라야 하는 경우가 있다.
pfunc(1,2); // 방식1.편의
(*pfunc)(1, 2); // 방식2.FM
}
함수 포인터 변수가 아닌 일반 함수 변수는 사용하지 않을까?
- 함수 변수는 단순히 함수 선언부이다. 따라서 linking 과정에서 같은 시그니처(이름 포함) 정의부현을 찾아서 해당 함수가 호출된다.
- 변수에 다른 함수를 넘길 수 없다.
#include <iostream>
using namespace std;
int func(int a, int b)
{
cout << "func()" << endl;
return a + b;
}
int func1(int a, int b)
{
cout << "func1()" << endl;
return a + b;
}
int main()
{
int (func)(int, int); // 일단적인 타입과 다르게 메모리에 적재 되지도 않음. 단순히 함수 선언부이다.
{
func = func1; // (x)
}
{
func(); // func 함수 정의가 있다면 호출. 없다면 링킹에러.
}
}
따라서 아래와 같은 방식으로 사용된다.
#include <iostream>
using namespace std;
int func(int a, int b)
{
return a + b;
}
int main()
{
// 선호 되는 방식
{
typedef int (*pfunc1)(int, int);
using pfunc2 = int(*)(int, int);
pfunc1 p1 = func;
pfunc2 p2 = func;
}
// 비선호 되는 방식
{
typedef int (pfunc1)(int, int);
using pfunc2 = int(int, int);
pfunc1* p1 = func;
pfunc2* p2 = func;
}
}
예외적인 사용법 - 멤버함수를 보관하는 함수
위와 같은 방식으로(전역, 정적 함수만 가능) 특정 클래스의 비정적 멤버함수를 변수에 받을 수 없다.
비정적 멤버함수를 변수로 받을 때는 전달방식, 호출방식 모두 차이가 있으니, 아래 코드를 통해 확인 하자.
#include <iostream>
using namespace std;
class Knight
{
public:
int func(int a, int b)
{
cout << "Knight:func()" << endl;
return a + b;
}
};
int main()
{
int (Knight::*pmfunc)(int, int);
{
pmfunc = Knight::func; // 일반적인 방식으로 전달 불가.(컴파일 에러)
pmfunc = &Knight::func; // FM으로 &연산자 사용 해야 함.
}
{
Knight k1;
k1.pmfunc(1, 2); // 불가
(k1.*pmfunc)(1, 2); // 가능(FM)
}
{
Knight* k1 = new Knight();
(k1->pmfunc)(1, 2); // 불가
(k1->*pmfunc)(1, 2); // 가능(FM)
}
}
공부한 내용을 개인적으로 복습하기 쉬운 형태로 정리했습니다.
잘못된 내용이 있는 경우 언제든 댓글 혹은 이메일로 지적해주시면 감사드립니다.
728x90
'Programming Language > C++' 카테고리의 다른 글
auto (0) | 2022.02.06 |
---|---|
함수 객체(함수자, Functor) (0) | 2022.02.06 |
2-2_입력( <<,manipulator,조정자) (0) | 2021.12.07 |
C++/StackPadding (0) | 2021.11.23 |
c/c++/size_t,intptr_t,uintptr_t (0) | 2021.11.23 |