A. 함수 포인터
1. 함수 포인터 기초
먼저 함수 객체를 이해하려면 함수 포인터에 대한 내용을 알아야 함
저번에 우선순위 q를 사용해 데이터를 꺼낼 때
정렬시 사용한 대소비교 객체가 무엇인지 (less, greater) 공부를 했었음
이 less, greater에 대한 공부임!!
a. 함수 포인터란?
🌟 함수를 가리키는 포인터
- int, double과 같은 자료구조들 뿐만 아니라 함수 자체도 포인터로 들고 있을 수 있음
- 다른 데이터 유형과 마찬가지로 메모리에 위치, 함수의 메모리 구조를 저장
- 👍 함수를 실행하는 시점을 뒤로 미룰 수 있다는게 장점
실행하는 시점을 뒤로 미룰 수 있다 ➡ 다양한 요청을 순서대로 처리한다
b. 함수 포인터 사용
1) 어떤 함수 작성
2) 함수 타입(FuncType) 생성
인트에다 데이터 타입이라는 별칭을 붙일 수 있는 것 처럼, 함수에 별칭을 붙일 수 있음
생성시에는 2가지 방식으로 설정할 수 있음
📘 문법
typedef 리턴타입 이름();
using 이름 = 리턴타입(); //조금 더 현대적
3) 그 생성한 함수 포인터에 함수를 넣어줄 수 있음
4) 호출
c. 인자가 있는 시그니처 타입
위에서는 void로 받았지만
만약 인자가 있는 함수를 포인터로 받아준다고 하면
👉 시그니처(리턴 타입)를 꼭 맞춰줘야 진행됨
💥 사용하지 않음
하지만 위에서 공부한 내용처럼 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) 사용하기
따라서 어떤 객체가 만들어져 있다고 가정하고 아래와같이 사용해야 함
언젠가 서버에서 활요할 일이 있기 때문에 알아둬야 한다
'자료구조와 알고리즘 > Data Structure' 카테고리의 다른 글
[게임 프로그래머 입문 올인원] STL Container : vector와 iterator (65, 66강) (0) | 2024.02.21 |
---|---|
[게임 프로그래머 입문 올인원] 함수 객체 (64강) (0) | 2024.02.19 |
[게임 프로그래머 입문 올인원] Maze Project : 그래프의 BFS기반 길찾기 (60강) (0) | 2024.02.19 |
그래프는 Vertex 구조체만 쓰기엔 아쉽다 (0) | 2024.02.18 |
[게임 프로그래머 입문 올인원] 비선형 자료구조 3 : 그래프 기초 (57강) (0) | 2024.02.17 |