함수도 다른 변수들 처럼 주소
를 가지고 있는데 이 함수의 주소를 포인터 변수에 저장해서 사용하는 걸 함수 포인터라고 합니다.
선언의 형태는 다음과 같습니다.
int (*f)(int, int);
// int - 리턴타입
// (*f) - 변수 이름 f를 함수포인터로 선언
//(int, int) 함수의 매개변수
이렇게 선언하면 함수의 주소값을 저장할 수 있는 f
라는 함수포인터가 만들어집니다.
이 f
라는 포인터 안에 함수의 주소
를 저장해서 사용할 수 있습니다.
#include <iostream>
using namespace std;
int add(int a, int b)
{
return (a + b);
}
int main(void)
{
int (*f)(int, int);
f = add; // 함수 add를 함수 포인터 f에 저장.
cout << f(1, 2) << endl;
}
//출력
//3
함수 포인터도 다른 변수와 동일하게 매개변수로 사용이 가능합니다.
#include <iostream>
using namespace std;
int add(int a, int b)
{
return (a + b);
}
void print_odd(int a, int b, int (*f)(int, int)) //매개변수로 함수 add를 받음
{
int ret = f(a, b);
if (ret % 2 == 1)
cout << ret << endl;
else
cout << "홀수가 아니에요!" << endl;
}
int main(void)
{
print_odd(2, 4, add);
print_odd(2, 3, add);
}
//출력
//홀수가 아니에요!
//5
함수포인터도 다른 변수들과 동일하게 const
를 사용할 수 있습니다.
#include <iostream>
using namespace std;
int add(int a, int b)
{
return (a + b);
}
int main(void)
{
int (*const f)(int, int) = add;
//참조 연산자 *옆에 const를 붙여주면 함수포인터 f를 상수화 시킬 수 있습니다.
cout << f(1, 2);
}
//출력
//3
class의 멤버함수도 함수포인터로 사용이 가능합니다.
하지만 class내부의 멤버함수는 객체
를 통해서만 출력이 가능하고, 함수포인터의 선언 또한 해당 클래스의 범위
내에있는 함수포인터라고 명시해줘야 사용이 가능합니다.
#include <iostream>
using namespace std;
class Test
{
public:
int add(int a, int b) //클래스 Test안에 멤버함수 add가 있습니다.
{
return (a + b);
}
};
int main(void)
{
Test test; // 클래스 Test를 인스턴스화 시켜 객체로 만듭니다.
int (Test::*f)(int, int) = &Test::add;
//함수포인터 f는 Test의 멤버함수를 사용하겠다고 Test::를 통해 명시해줍니다.
//그리고 함수의 주소 또한 Test의 멤버함수라고 명시해 주고 다른 함수 포인터와 달리
//항상 명시적으로 &연산자를 통해 함수의 주소를 가져와야 합니다.
cout << (test.*f)(1, 2) << endl;
//함수포인터의 사용 또한 해당 클래스의 객체를 통해서 사용해야 합니다.
//만약 class의 멤버함수 내에서 함수포인터를 사용한다면 this를 통해서 접근할 수 있습니다.
//접근은 멤버 포인터 연산자인 .* 또는 ->*연산자로 접근해야 합니다.
}
//출력
//3
진짜 못 알아 먹게 생겼다.
함수포인터 정말 못 생긴 것 같아요.
하지만 아직 하나 더 남았어요. 그래도 이건 일반 함수포인터와 비슷하게 사용합니다.
class에서 멤버함수에 static
을 사용하면 class의 이름
으로 해당 함수에 접근이 가능하고, 어떤 특정 객체에 귀속
되는게 아니라고 했었습니다.
그렇기 때문에 class의 이름을 통해서 접근만 해주면 일반 함수포인터와 동일하게 사용이 가능합니다.
#include <iostream>
using namespace std;
class Test //class를 총 4개 생성한 뒤 멤버함수 모두 static을 사용해 줍니다.
{
public:
static int add(int a, int b)
{
return (a + b);
}
};
class TestTwo
{
public:
static int sub(int a, int b)
{
return (a - b);
}
};
class TestThree
{
public:
static int div(int a, int b)
{
return (a / b);
}
};
class TestFour
{
public:
static int mul(int a, int b)
{
return (a * b);
}
};
int main(void)
{
//함수포인터의 배열을 선언해주고, class의 이름을 통해서 함수의 주소를 저장해줍니다.
int (*f[4])(int, int) = {
&Test::add,
&TestTwo::sub,
&TestThree::div,
&TestFour::mul
};
for (int i = 0; i < 4; i++)
cout << f[i](1, 2) << endl;
//출력은 일반 함수포인터와 동일합니다.
}
//출력
//3
//-1
//0
//2
참고
[ c++ ] namespace
[ c++ ] 클래스, 생성자, 소멸자, 이니셜라이저, this포인터
[ c++ ] c++에서의 const와 static
[ c++ ] 참조자(reference)
[ c++ ] new와 delete
[ c++ ] 함수 오버로딩
[ c++ ] 파일 입출력 (ifstream, ofstream)
[ c++ ] 함수포인터, 멤버 함수포인터
[ c++ ]연산자 오버로딩
[ c++ ] 캡슐화란?
[ c++ ] 상속과 다형성에 대해 알아보자