Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 7: 포인터Topic 4: 함수 포인터

Topic 4: 함수 포인터 🎯⚡

🎯 학습 목표

  • 함수 포인터의 개념과 필요성을 이해할 수 있다
  • 함수 포인터 선언과 사용법을 익힐 수 있다
  • 콜백 함수의 원리를 이해하고 구현할 수 있다
  • 함수 포인터를 활용한 유연한 프로그래밍을 할 수 있다

📖 함수 포인터란?

함수 포인터는 함수의 주소를 저장하는 특별한 포인터입니다. 변수가 메모리에 저장되듯이, 함수도 메모리에 저장되며 고유한 주소를 가집니다.

아날로지: 전화번호부와 같습니다.

  • 함수 이름: 연락처 이름 (김철수, 이영희)
  • 함수 포인터: 전화번호 - 실제 통화할 때 사용
  • 함수 호출: 전화 걸기

🔍 함수 포인터 기본 문법

#include <iostream> using namespace std; // 간단한 함수들 int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } int main() { cout << "=== 함수 포인터 기초 ===" << endl; // 함수 포인터 선언과 초기화 int (*operation)(int, int) = add; // add 함수의 주소 저장 // 함수 포인터를 통한 함수 호출 int result = operation(5, 3); // add(5, 3)과 동일 cout << "5 + 3 = " << result << endl; // 다른 함수로 변경 operation = multiply; // multiply 함수의 주소로 변경 result = operation(5, 3); // multiply(5, 3)과 동일 cout << "5 * 3 = " << result << endl; return 0; }

🎮 실습: 계산기 만들기

#include <iostream> using namespace std; // 계산 함수들 int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int divide(int a, int b) { return (b != 0) ? a / b : 0; } // 함수 포인터를 매개변수로 받는 함수 void calculate(int x, int y, int (*operation)(int, int), const char* symbol) { int result = operation(x, y); cout << x << " " << symbol << " " << y << " = " << result << endl; } int main() { cout << "=== 함수 포인터 계산기 ===" << endl; int a = 10, b = 3; // 각 연산을 함수 포인터로 실행 calculate(a, b, add, "+"); calculate(a, b, subtract, "-"); calculate(a, b, multiply, "*"); calculate(a, b, divide, "/"); return 0; }

📞 콜백 함수 (Callback Functions)

콜백 함수는 다른 함수에 인자로 전달되어 특정 상황에서 호출되는 함수입니다.

🔄 콜백 함수 예제

#include <iostream> using namespace std; // 콜백 함수들 void onSuccess() { cout << "✅ 작업이 성공적으로 완료되었습니다!" << endl; } void onError() { cout << "❌ 작업 중 오류가 발생했습니다!" << endl; } // 작업을 수행하고 결과에 따라 콜백 호출 void doWork(bool willSucceed, void (*successCallback)(), void (*errorCallback)()) { cout << "작업을 시작합니다..." << endl; // 가상의 작업 수행 if(willSucceed) { cout << "작업 진행 중..." << endl; successCallback(); // 성공 콜백 호출 } else { cout << "문제가 발생했습니다..." << endl; errorCallback(); // 오류 콜백 호출 } } int main() { cout << "=== 콜백 함수 예제 ===" << endl; // 성공 케이스 cout << "\n--- 성공 케이스 ---" << endl; doWork(true, onSuccess, onError); // 실패 케이스 cout << "\n--- 실패 케이스 ---" << endl; doWork(false, onSuccess, onError); return 0; }

🔧 함수 포인터 배열

여러 함수를 배열에 저장하여 필요할 때 선택적으로 호출할 수 있습니다.

#include <iostream> using namespace std; // 다양한 인사 함수들 void sayHello() { cout << "안녕하세요!" << endl; } void sayGoodbye() { cout << "안녕히 가세요!" << endl; } void sayWelcome() { cout << "환영합니다!" << endl; } int main() { cout << "=== 함수 포인터 배열 ===" << endl; // 함수 포인터 배열 선언 void (*greetings[3])() = {sayHello, sayGoodbye, sayWelcome}; // 메뉴 출력 cout << "\n선택하세요:" << endl; cout << "0: 인사하기" << endl; cout << "1: 작별하기" << endl; cout << "2: 환영하기" << endl; int choice; cout << "선택 (0-2): "; cin >> choice; // 선택에 따라 함수 호출 if(choice >= 0 && choice <= 2) { greetings[choice](); // 함수 포인터 배열로 호출 } else { cout << "잘못된 선택입니다!" << endl; } return 0; }

🎯 실습: 배열 처리 함수들

#include <iostream> using namespace std; // 배열 처리 함수들 void printArray(int* arr, int size, const char* title) { cout << title << ": "; for(int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; } void doubleValues(int* arr, int size) { for(int i = 0; i < size; i++) { arr[i] *= 2; } } void addTen(int* arr, int size) { for(int i = 0; i < size; i++) { arr[i] += 10; } } void resetToZero(int* arr, int size) { for(int i = 0; i < size; i++) { arr[i] = 0; } } // 배열 처리 함수를 실행하는 함수 void processArray(int* arr, int size, void (*processor)(int*, int), const char* description) { cout << description << endl; processor(arr, size); } int main() { cout << "=== 함수 포인터로 배열 처리 ===" << endl; int numbers[5] = {1, 2, 3, 4, 5}; printArray(numbers, 5, "초기 배열"); // 함수 포인터를 사용한 배열 처리 processArray(numbers, 5, doubleValues, "값들을 2배로 만듭니다..."); printArray(numbers, 5, "2배 후"); processArray(numbers, 5, addTen, "모든 값에 10을 더합니다..."); printArray(numbers, 5, "10 추가 후"); processArray(numbers, 5, resetToZero, "배열을 초기화합니다..."); printArray(numbers, 5, "초기화 후"); return 0; }

💡 함수 포인터 활용 팁

✅ 언제 사용하면 좋을까?

  1. 메뉴 시스템: 사용자 선택에 따른 다른 함수 실행
  2. 이벤트 처리: 특정 상황에서 호출할 함수 지정
  3. 정렬 알고리즘: 다양한 비교 조건으로 정렬
  4. 콜백 시스템: 작업 완료 후 호출할 함수

🔍 간단한 활용 예제

#include <iostream> using namespace std; // 배열 출력 함수 void showArray(int* arr, int size) { for(int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; } // 배열에서 조건에 맞는 요소 찾기 int findFirst(int* arr, int size, bool (*condition)(int)) { for(int i = 0; i < size; i++) { if(condition(arr[i])) { return i; // 인덱스 반환 } } return -1; // 찾지 못함 } // 조건 함수들 bool isEven(int n) { return n % 2 == 0; } bool isLarge(int n) { return n > 50; } int main() { cout << "=== 조건부 검색 예제 ===" << endl; int data[6] = {15, 30, 45, 60, 75, 90}; cout << "배열: "; showArray(data, 6); // 첫 번째 짝수 찾기 int evenIndex = findFirst(data, 6, isEven); if(evenIndex != -1) { cout << "첫 번째 짝수: " << data[evenIndex] << " (인덱스 " << evenIndex << ")" << endl; } // 50보다 큰 첫 번째 수 찾기 int largeIndex = findFirst(data, 6, isLarge); if(largeIndex != -1) { cout << "50보다 큰 첫 번째 수: " << data[largeIndex] << " (인덱스 " << largeIndex << ")" << endl; } return 0; }

⚠️ 주의사항

❌ 피해야 할 실수

  1. 초기화되지 않은 함수 포인터

    int (*ptr)(int, int); // 초기화되지 않음 // int result = ptr(1, 2); // 위험!
  2. 잘못된 함수 시그니처

    int add(int a, int b) { return a + b; } void (*wrongPtr)(int, int) = add; // 반환형이 다름!

✅ 안전한 사용법

#include <iostream> using namespace std; int add(int a, int b) { return a + b; } int main() { // 안전한 초기화 int (*safePtr)(int, int) = add; // nullptr 체크 if(safePtr != nullptr) { cout << "결과: " << safePtr(5, 3) << endl; } return 0; }

🧪 퀴즈 타임!

🤔 퀴즈 1: 함수 포인터 선언

다음 중 올바른 함수 포인터 선언은?

int square(int x) { return x * x; }
  1. int* ptr = square;
  2. int (*ptr)(int) = square;
  3. int ptr(int) = square;
  4. (*ptr)(int) = square;

정답: 2번

함수 포인터는 반환형 (*포인터명)(매개변수) 형태로 선언합니다.

🤔 퀴즈 2: 콜백 함수

다음 코드의 출력 결과는?

void callback() { cout << "콜백 실행!" << endl; } void process(void (*cb)()) { cb(); } process(callback);

정답: “콜백 실행!”

함수 포인터를 통해 callback 함수가 호출됩니다.

🎯 연습 문제

연습 1: 간단한 메뉴 시스템

함수 포인터 배열을 사용해서 사용자가 선택한 메뉴에 따라 다른 함수를 실행하는 프로그램을 만들어 보세요.

💡 힌트

void menu1() { cout << "메뉴 1 실행" << endl; } void menu2() { cout << "메뉴 2 실행" << endl; } void (*menus[])() = {menu1, menu2};

연습 2: 배열 정렬하기

함수 포인터를 사용해서 오름차순/내림차순으로 정렬할 수 있는 프로그램을 만들어 보세요.

💡 힌트

bool ascending(int a, int b) { return a > b; } bool descending(int a, int b) { return a < b; } void bubbleSort(int* arr, int size, bool (*compare)(int, int));

🎉 마무리

함수 포인터는 프로그램을 더 유연하고 재사용 가능하게 만드는 강력한 도구입니다!

오늘 배운 내용:

  • 🎯 함수 포인터의 개념과 기본 문법
  • 📞 콜백 함수의 원리와 활용
  • 🔧 함수 포인터 배열을 통한 선택적 실행
  • 💡 실전 활용 방법과 주의사항

다음 단계:

  • Unit 9에서는 참조(Reference)를 학습합니다
  • 포인터보다 안전하고 간편한 참조의 사용법을 배우게 됩니다
  • 함수 매개변수에서의 참조 활용도 다루게 됩니다

함수 포인터를 잘 활용하면 더 유연하고 확장 가능한 프로그램을 만들 수 있습니다! 💪

Last updated on