Menu
Coddy logo textTech

구조체 내의 함수 포인터

Coddy C 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 38번째.

지금까지는 function pointer를 독립적인 변수로 사용하거나 인수로 전달했습니다. 다형성을 향한 다음 단계는 function pointer를 struct 내부에 직접 삽입하여 struct 자체에 고유한 동작을 부여하는 것입니다.

구조체가 function pointer를 포함하면 각 instance는 서로 다른 함수를 보유할 수 있습니다. 즉, 동일한 type의 두 객체는 해당 function pointer를 호출할 때 서로 다르게 동작할 수 있습니다.

typedef void (*PrintFunc)(const char*);

typedef struct {
    const char* name;
    PrintFunc print;  // 멤버로서의 함수 포인터
} Printer;

Printer 구조체는 이제 두 개의 멤버를 가집니다. 데이터(name)와 동작(print)입니다. 이를 사용하려면 초기화하는 동안 포인터에 함수를 할당합니다.

void loud_print(const char* msg) {
    printf("!!! %s !!!\n", msg);
}

int main() {
    Printer p;
    p.name = "Alert";
    p.print = loud_print;
    
    p.print("Hello");  // 출력: !!! Hello !!!
    return 0;
}

struct를 통해 함수를 호출하는 방식에 주목하세요: p.print("Hello"). 이는 다른 언어에서 객체의 메서드를 호출하는 것과 매우 비슷해 보입니다. struct는 자신의 데이터와 그 데이터에 대해 작동하는 함수를 모두 포함합니다.

이 패턴은 C에서 다형성의 기반입니다. 서로 다른 instance에는 서로 다른 function을 할당할 수 있으며, 동일한 struct 유형에서 서로 다른 동작을 만들어 냅니다.

challenge icon

챌린지

쉬움

Notifier 시스템을 만들어 구조체가 function pointer를 통해 자체 동작을 전달할 수 있음을 보여 줍시다.

코드를 정리하기 위해 두 개의 파일을 만들 것입니다:

  • notifier.h: const char* parameter를 받고 아무것도 반환하지 않는 NotifyFunc라는 function pointer type을 Define합니다. 그런 다음 name(const char*)과 NotifyFunc type의 notify function pointer를 포함하는 Notifier 구조체를 Define합니다.
  • main.c: header를 include하고 두 개의 notification function을 Implement합니다:
    • alert_notify: 다음 형식으로 message를 출력합니다: [ALERT] message
    • info_notify: 다음 형식으로 message를 출력합니다: [INFO] message
    그런 다음 Notifier instance를 Create하고, input에 Based하여 appropriate function을 연결한 뒤, 구조체의 function pointer를 통해 notification을 Call합니다.

프로그램은 두 가지 input을 받습니다. notification type(alert는 1, info는 2)과 표시할 message입니다.

type에 Based하여 해당 function을 notifier의 notify member에 assign한 다음, 구조체를 통해 이를 Call하여 message를 표시합니다.

type이 1이고 message가 "System starting"일 때의 출력 예시:

[ALERT] System starting

type이 2이고 message가 "All systems normal"일 때의 출력 예시:

[INFO] All systems normal

header 파일에서 include guards를 사용하고, 구조체 member를 통해 function을 Call해야 한다는 점을 기억하세요: n.notify(message)

직접 해보기

#include <stdio.h>
#include "notifier.h"

// TODO: alert_notify 함수 구현
// 출력해야 함: [ALERT] message


// TODO: info_notify 함수 구현
// 출력해야 함: [INFO] message


int main() {
    int type;
    char message[256];
    
    // 입력 읽기
    scanf("%d", &type);
    getchar(); // 개행 소비
    fgets(message, sizeof(message), stdin);
    
    // 메시지에 후행 개행이 있으면 제거
    int len = 0;
    while (message[len] != '\0') len++;
    if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
    
    // TODO: Notifier 인스턴스 생성
    
    
    // TODO: type에 따라 (1은 alert, 2는 info),
    // 적절한 함수를 notifier의 notify 멤버에 할당
    
    
    // TODO: 구조체의 함수 포인터를 통해 알림 호출
    // 사용: n.notify(message)
    
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 C 컴파일러