본문 바로가기
공부

[자료구조] 함수포인터

by MY블로그 2023. 5. 24.

함수 포인터

함수도 다른 변수들처럼 자신의 [주소]를 가지고 있습니다.

이 함수의 주소를 포인터 변수에 저장하여 사용할 수 있는 것을 함수 포인터 라고 합니다.

[ 함수 포인터 예제 ]
int (*f)(int, int); = 리턴타입(*포인터이름)(매개변수1, 매개변수2 / 단,매개변수없을시 () 또는 void);

위의 형태로 선언 할 수 있습니다.

위처럼 선언하였을때 함수의 주소값을 저장할 수 있는 [ 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; // 생성한 f 함수포인터에 add 함수의 주소를 넣습니다.
    
   	cout << f(11,22) << endl; // add(11 + 22)실행 33출력
    
	return 0;
}

위처럼 만들어져 있는 함수를 함수포인터에 넣어주고 함수포인터로 함수를 실행할 수 있습니다.


매개 변수로 사용 가능한 함수 포인터

함수 포인터는 다른 변수처럼 매개 변수로 사용할 수 있습니다.

 

[ 매개변수로 함수 포인터 사용 예제 ]
#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)) // 매개변수1, 매개변수2, 매개변수3(함수포인터)
{
	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(1, 4, add); // 홀수조건이므로 결과로 5 출력

	return 0;
}

함수 포인터의 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 선언으로 상수화
    
	cout << f(1,2) << endl; // 출력결과 3
    
	return 0;
}

class 멤버함수의 함수 포인터

클래스의 멤버함수도 함수 포인터로 사용이 가능합니다.

단, 클래스 내부의 멤버함수는 꼭 [객체]를 통해서만 접근이 가능합니다.

또한 함수포인터의 선언은 해당 클래스의 [범위]내에있는 함수포인터라고 명시한후 사용 가능합니다.

#include <iostream>
using namespace std;

class Test // 클래스 선언
{
public:
	int add(int a, int b) // 클래스 내부에 위치한 함수 add
    {
    	return (a + b); // 매개변수 두개를 더해서 반환
    }
};

int main(void)
{
	Test test; // Test 클래스를 인스턴스화 시켜서 test 객체를 생성 합니다.
    int (Test::*f)(int, int) = &Test::add;
    // 함수 포인터 [ f ] 는 Test의 멤버함수를 사용하기위해서 Test::(범위접근) 을 명시합니다.
    // 함수의 주소 또한 Test의 멤버함수임을 명시해 주고 [ &Test:: ]
    // 위처럼 꼭 & 참조 연산자를 통해서 주소를 가져와야 합니다.
    
    cout << (test.*f)(1,2) << endl; // test 객체의 함수 add 호출 출력 : 3
    // 함수포인터는 생성된 클래스 객체를 통해서 호출이 가능합니다.
    // 만일 클래스 멤버함수 내에서 함수포인터를 사용한다면 그때는 [ this ] 를 통해서 접근합니다.
    // 접근 멤버 포인터 연산자인 [ .* ] 혹은 [ ->* ] 연산자로 접근해야 합니다. 

	return 0;
}

static(정적)을 이용한 멤버함수 접근

class 에서 멤버함수에 static 을 사용한다면 class 의 이름 으로 해당 함수에 접근이 가능하며,

어떤  특정 객체에 귀속 되지 않습니다.

때문에 class 의 이름을 통해서 접근만 해준다면 일반 함수포인터와 동일하게 사용이 가능합니다.

#include <iostream>
using namespace std;

class Test1 // 1클래스 생성
{
public:
	static int add(int a, int b) // [+ 함수]
    {
    	return (a + b);
    }
};

class Test2 // 2클래스 생성
{
public:
	static int sub(int a, int b) // [- 함수]
    {
    	return (a - b);
    }
};

class Test3 // 3클래스 생성
{
public:
	static int div(int a, int b) // [/ 함수]
    {
    	return (a / b);
    }
};

class Test4 // 4클래스 생성
{
public:
	static int mul(int a, int b) // [* 함수]
    {
    	return (a * b);
    }
};

int main(void)
{
	//함수 포인터의 배열을 선언 합니다.
    //선언 후 class 의 이름을 통하여 함수의 주소를 저장 합니다.
	int (*f[4])(int, int) = {
    	&Test1::add,
        &Test2::sub,
        &Test3::div,
        &Test4::mul
    };
    for(int i = 0, i < 4; i++)
    {
    	cout << f[i](1,2) << endl; // 함수포인터처럼 출력됩니다.
        // 함수 순서대로 의결과 3, -1, 0, 2 출력
    }

	return 0;
}

 

 

댓글