모던 C++와 C 대안

C++의 다형성과 C의 함수 포인터 테이블

이 레슨에서는 C++의 가상 함수와 C의 함수 포인터로 여러 종류의 객체에 같은 연산을 호출합니다.

소개

동적 다형성(dynamic polymorphism)은 코드가 넓이 계산 같은 공통 연산을 호출하고, 그 연산을 어떻게 할지는 각 객체 타입이 스스로 정하게 합니다. C++는 가상 함수(virtual functions)로 이를 직접 지원하며, C에서는 함수 포인터로 흉내 낼 수 있습니다.

핵심 정리

  • C++의 추상화를 배우기 전에 C에서는 어떻게 하는지 이해하세요.
  • 자원의 소유권은 RAII와 값 의미론(value semantics)으로 표현하세요.
  • 매크로와 타입 변환보다 C++의 타입 안전한 도구를 쓰세요.

C와 C++ 코드 예제

C
실행 →
main.c
#include <stdio.h>

typedef struct Shape Shape;
struct Shape {
    double value;
    double (*area)(const Shape *shape);
};

double square_area(const Shape *shape) {
    return shape->value * shape->value;
}

int main(void) {
    Shape square = {4.0, square_area};
    printf("area=%.1f\n", square.area(&square));
}
실행 결과
area=16.0
C++
실행 →
main.cpp
#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double side;

    explicit Square(double value) : side(value) {}
    double area() const override { return side * side; }
};

int main() {
    Square square(4);
    const Shape& shape = square;
    std::cout << "area=" << shape.area() << '\n';
}
실행 결과
area=16

C와 C++ 비교

C의 struct Shape에는 함수 포인터 area가 들어 있고, 도형마다 square_area처럼 자기만의 넓이 계산 함수를 연결합니다. C++에서는 가상 함수가 같은 선택 메커니즘을 자동으로 만들어 줍니다. 기반 클래스 포인터로 객체를 안전하게 삭제하려면 기반 클래스에 가상 소멸자(virtual destructor)도 있어야 합니다.

C

C는 이름 짓기 관례, 콜백, 매크로, 컨텍스트 struct를 씁니다.

C++

C++는 범위가 분명하고 타입 안전하며, 보통 실행 시 추가 비용이 없는 추상화를 제공합니다.

연습 문제

두 버전을 모두 실행한 다음 코드를 바꿔 보면서 각 언어가 주는 안전성의 차이를 살펴보세요.

  • 먼저 C로 동작 원리를 작성한 다음 C++의 같은 기능을 써 보세요.
  • 직접 하던 자원 해제를 RAII로 바꿔 보세요.
  • 그 기능이 메모리 할당이나 가상 함수 호출을 일으키는지 확인해 보세요.

챌린지로 연습하기

이 레슨에서 배운 내용으로 실제 문제를 풀어 보세요. 모든 챌린지는 브라우저에서 실행되며 즉시 테스트와 AI 리뷰를 받을 수 있습니다.

모든 챌린지