Menu
Coddy logo textTech

구조체 임베딩

Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 28번째.

C++나 Java와 같은 객체 지향 언어에서 상속은 클래스가 부모 클래스로부터 속성을 물려받을 수 있게 해줍니다. C에는 내장된 상속 기능이 없지만, 하나의 struct를 다른 struct 내부에 배치하는 composition(합성)이라는 기법을 사용하여 이를 흉내 낼 수 있습니다.

아이디어는 간단합니다: 만약 ChildParent의 모든 속성을 필요로 한다면, Parent 구조체를 Child의 멤버로 포함(embed)합니다.

typedef struct {
    int id;
    char name[50];
} Parent;

typedef struct {
    Parent parent;  // 포함된 구조체
    int grade;
} Child;

여기서 ChildParent가 가진 모든 것과 더불어 자신의 grade 필드를 포함합니다. 이것은 합성(composition)입니다. 즉, 자식은 부모 "이다(is a)"가 아니라 부모를 "가지고 있는(has a)" 것이지만, 그 효과는 상속과 유사합니다.

자식 인스턴스를 통해 부모의 멤버에 접근하려면 점(dot) 연산자를 두 번 사용합니다:

Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;

이 패턴은 C에서 타입 계층 구조를 구축하기 위한 기초를 형성합니다. 기본 struct를 첫 번째 멤버로 포함함으로써, 향후 레슨에서 살펴볼 강력한 기법들을 활용할 수 있게 됩니다.

challenge icon

챌린지

쉬움

C 언어에서 상속의 기초가 되는 구조체 임베딩(struct embedding)을 보여주는 간단한 직원 관리 시스템을 만들어 보겠습니다.

EmployeePerson을 포함하는 계층 구조를 만들 것입니다. 이는 상속이 작동하는 방식과 유사합니다. 직원은 추가적인 업무 관련 정보를 가진 사람("is a" person)입니다. Employee 구조체 안에 Person 구조체를 임베딩함으로써, 사람의 모든 속성과 직원 전용 필드를 모두 가질 수 있습니다.

코드는 세 개의 파일로 구성됩니다:

  • types.h: 인클루드 가드(include guards)와 함께 두 구조체를 정의합니다. 먼저, name (50자의 문자 배열)과 age (정수)라는 두 필드를 가진 Person 구조체를 만듭니다. 그런 다음 Person을 첫 번째 멤버로 포함하고 employee_id 필드(정수)를 추가한 Employee 구조체를 정의합니다.
  • types.c: Employee에 대한 포인터를 받아 정보를 출력하는 print_employee 함수를 구현합니다. 이전에 배운 체인 형태의 점(.) 또는 화살표(->) 구문을 사용하여 임베딩된 사람의 데이터에 접근하세요.
  • main.c: Employee 변수를 생성하고, 모든 필드(임베딩된 사람의 이름과 나이 포함)를 채운 뒤, 출력 함수를 사용하여 정보를 표시합니다.

세 가지 입력을 받게 됩니다: 직원의 이름 (문자열), 나이 (정수), 그리고 직원 ID (정수).

print_employee 함수는 다음과 같은 형식으로 직원의 정보를 출력해야 합니다:

Employee: Alice
Age: 28
ID: 1001

여기서 Alice는 이름, 28은 나이, 1001은 입력받은 직원 ID입니다.

임베딩된 구조체의 멤버에 접근할 때는 부모 멤버를 거쳐야 한다는 점을 기억하세요. 예를 들어, 이름에 접근하려면 먼저 person 멤버를 거쳐야 합니다.

치트 시트

C 언어에는 내장된 상속 기능이 없지만, 한 구조체를 다른 구조체 안에 포함시키는 구성(composition)을 사용하여 이를 시뮬레이션할 수 있습니다.

부모-자식 관계를 만들려면, 부모 구조체를 자식 구조체의 멤버로 포함시키세요:

typedef struct {
    int id;
    char name[50];
} Parent;

typedef struct {
    Parent parent;  // 포함된 구조체
    int grade;
} Child;

자식 구조체는 부모의 모든 속성과 자신만의 추가 필드를 포함합니다. 이는 "has a" 관계를 나타냅니다.

포함된 구조체의 멤버에 접근하려면 점(dot) 연산자를 두 번 사용합니다:

Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;

포인터를 사용할 때는 화살표 연산자를 사용하여 포함된 구조체의 멤버에 접근합니다:

Child *ptr = &c;
ptr->parent.id = 101;
ptr->grade = 5;

기본 구조체를 첫 번째 멤버로 포함시키는 것은 C에서 타입 계층 구조를 구축하기 위한 고급 기술을 가능하게 하는 일반적인 패턴입니다.

직접 해보기

#include <stdio.h>
#include <string.h>
#include "types.h"

int main() {
    // 입력 읽기
    char name[50];
    int age;
    int employee_id;
    
    fgets(name, 50, stdin);
    name[strcspn(name, "\n")] = '\0';  // 줄바꿈 문자 제거
    scanf("%d", &age);
    scanf("%d", &employee_id);
    
    // TODO: Employee 변수 생성
    
    // TODO: 포함된 person의 name과 age 채우기
    // Hint: name에는 strcpy를 사용하고, employee.person.name으로 접근하세요
    
    // TODO: employee_id 설정
    
    // TODO: employee의 포인터를 사용하여 print_employee 호출
    
    return 0;
}
quiz icon실력 점검

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

Object Oriented Programming의 모든 레슨