자료구조와 알고리즘/Data Structure

[게임 프로그래머 입문 올인원] 함수 포인터 (63강)

순정법사 2024.02.19

A. 함수 포인터

1. 함수 포인터 기초

먼저 함수 객체를 이해하려면 함수 포인터에 대한 내용을 알아야 함

 

더보기

저번에 우선순위 q를 사용해 데이터를 꺼낼 때

정렬시 사용한 대소비교 객체가 무엇인지 (less, greater) 공부를 했었음

이 less, greater에 대한 공부임!!

 

a. 함수 포인터란?

🌟 함수를 가리키는 포인터

 

  • int, double과 같은 자료구조들 뿐만 아니라 함수 자체도 포인터로 들고 있을 수 있음
  • 다른 데이터 유형과 마찬가지로 메모리에 위치, 함수의 메모리 구조를 저장
  • 👍 함수를 실행하는 시점을 뒤로 미룰 수 있다는게 장점

 

실행하는 시점을 뒤로 미룰 수 있다 ➡ 다양한 요청을 순서대로 처리한다

 

b. 함수 포인터 사용

1) 어떤 함수 작성

 

 

2) 함수 타입(FuncType) 생성

 

인트에다 데이터 타입이라는 별칭을 붙일 수 있는 것 처럼, 함수에 별칭을 붙일 수 있음

 

생성시에는 2가지 방식으로 설정할 수 있음

 

📘 문법

typedef 리턴타입 이름();

using 이름 = 리턴타입();	//조금 더 현대적

 

~ = int는 예시

 

3) 그 생성한 함수 포인터에 함수를 넣어줄 수 있음 

 

& 생략 가능

 

4) 호출

 

ptr();

 

c. 인자가 있는 시그니처 타입

위에서는 void로 받았지만

만약 인자가 있는 함수를 포인터로 받아준다고 하면

 

👉 시그니처(리턴 타입)를 꼭 맞춰줘야 진행됨

 

int(int, int)처럼 맞춰주야 함

 

💥 사용하지 않음

하지만 위에서 공부한 내용처럼 FuncType을 만들어 독립적으로 쓰는 경우는 사실상 없음
위와같이 나눠서 사용하지 않고, 한 번에 포인터 함수에 포인터 타입을 만들어서 사용하는 경우가 대부분

 

d. 함수 포인터를 한번에 만드는 방법

void Print();	//1.함수를 적어주고
void(*)();	//2. 함수 이름을 제거한 후 (포인터) 넣어주기
using f = void(*)();	//3. using ~로 받아주기

 

즉 아래와 같은 문법이 만들어짐

 

📘 문법

//void를 뱉어주고 void를 받아주는 함수의 포인터타입을 FuncPtrType이라고 부르겠다
using FuncPtrType = void(*)();	
FuncPtrType ptr = &Print;
ptr(); //호출

 

e. 함수 포인터의 사용환경

1) 행동 자체를 인자로 넘기고 싶을 때

즉, 가위바위보를 한다는 행위 자체를 포인터에 저장한 후
가위, 바위, 보를 각각 다른 함수로 지정할 수 있게 하기 위함

이 예제는 덧셈 뺄셈

 

2) 콜백 함수

 

  • UI : 어떤 버튼을 눌렀을 때 실행되는 함수를 맵핑해 서버에 연결되게 하는 경우
  • 서버 : 사용자가 입장시 서버에서 행동을 설정할 수 있게 만들어줄 때 
  • 키보드 : 동작 커스터마이징 시 입력에 대한 처리를 쉽게 하기 위해 


3) 예시

 

 

아이템 찾기

➡ 아이템의 여러가지 정보에 대한 내용을 포인터로 저장해 따로 생성함

 

이런 느낌

 

💥 나중에 람다식으로 사용해 IsRare처럼 함수를 따로 만들지 않음

 

f. 함수 포인터의 한계

1) 타입 안정성 부족

 

포인터 사용시 컴파일러가 타입을 확인할 수 없는 경우가 있음

 

2) 가독성과 유지보수성의 저하

 

코드가 복잡해져 유지보수성을 저하

 

3) 함수 호출 오버헤드

 

일부 언어나 컴파일러에서의 포인터를 통한 함수 호출은 직접 호출보다 느릴 수 있음

(간접적으로 호출하는데 필요한 추가 오버헤드 때문)

 

4) 제한된 컴파일 타입 최적화

 

컴파일 타임에 최적화할 수 있는 기회가 제한될 수있음

(컴파일러는 함수 포인터가 가리키는 함수의 실제 호출 코드를 알지 못함 )

 

5) 포인터 연산의 제한

 

일부 환경에서는 포인터 연산을 허용하지 않음

 

 

2. 멤버 함수 포인터

진짜 활용할 일 없긴 하다

a. 멤버 함수란?

🌟 클래스에 종속되어 사용되는 함수

 

이런 모습

 

💥 전역함수나 static 키워드가 붙은 정적 함수는 멤버 함수와 다름

 

b. 함수 호출 규약

🌟 함수를 호출할 때 전달되는 인자들의 순서라거나 함수가 종료될 때 스택을 누가 정리할지 정하는 것

 

  • 일반함수 : cdecl
  • 멤버함수 :thiscall 

 

위에서 생성한 멤버 함수를 함수 포인터로 사용할 수 없는이유는

👉 바로 이 함수 호출 규약이 달라서 그럼

 

1) 설명

 

 

실제로 위 코드를 실행시켜보면

t.PrintTest는 자기 자신의 주소를 넘기는 식으로 되어있음

 

c. 멤버 함수 포인터 생성하기

1) 포인터 함수라고 정의하기

 

포인터는 포인터함수인데 

::를 붙여서

테스트 안에 있는 어떤 함수포인터를

멤버 함수 ptr 타입이라고 정의 

 

 

2) 포인터 타입에 담기

 

위와같이 사용하면 포인터타입에 멤버함수를 담을 순 있지만 

 

 

멤버 함수 자체가 특정 객체를 대상으로 실행되는 것이기 때문에 단독으로 실행할 수 없음

 

3) 사용하기

 

따라서 어떤 객체가 만들어져 있다고 가정하고 아래와같이 사용해야 함

 

위는 객체 / 아래는 포인터일시

 

언젠가 서버에서 활요할 일이 있기 때문에 알아둬야 한다

 

 

 


출처 : https://www.inflearn.com/course/%EA%B2%8C%EC%9E%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8-%EC%9E%85%EB%AC%B8-%EC%98%AC%EC%9D%B8%EC%9B%90-rookiss#curriculum

 

[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버 -

어디부터 시작할지 막막한 게임 프로그래밍 입문자를 위한 All-In-One 커리큘럼입니다. C++, 자료구조/알고리즘, STL, 게임 수학, Windows API, 게임 서버 입문으로 이어지는 알찬 커리큘럼으로 게임 프

www.inflearn.com