[C++] struct vs class: 언제 무엇을 써야 할까?

Ma_Seokjae·2025년 10월 21일
post-thumbnail

C++에서 structclass거의 같은 기능을 가집니다.
하지만 이 “거의” 안에 중요한 차이가 숨어 있습니다.
바로 기본 접근제한자기본 상속제한자입니다.

이 작은 차이는 단순한 문법 차원이 아니라, 코드의 의도(데이터 중심 vs 캡슐화 중심)설계 철학을 드러내는 중요한 신호입니다.

따라서, 이번 글에서는

  • 두 키워드의 정확한 차이
  • 선택 기준
  • C 언어의 struct와의 차이점

을 정리해보겠습니다.


1. 문법 차이: “기본 접근 범위”와 “기본 상속 방식”

기본 접근제한자

struct S {
    int x;           // 기본적으로 public
    void hello();    // 기본적으로 public
};

class C {
    int x;           // 기본적으로 private
    void hello();    // 기본적으로 private
public:
    C();             // 명시적으로 공개해야 함
};
  • struct는 기본적으로 모든 멤버가 public,
  • class는 기본적으로 모든 멤버가 private입니다.

기본 상속제한자

struct Base {};
struct Derived : Base { };     // 기본적으로 public 상속

class Base2 {};
class Derived2 : Base2 { };    // 기본적으로 private 상속
  • struct는 상속 시 public 상속이 기본,
  • classprivate 상속이 기본입니다.

2. 둘 중 어떤 걸 사용해야 할까?

C++에서 두 키워드는 역할이 아니라 의도(intent) 를 표현합니다.
즉, “이 타입이 어떤 목적으로 만들어졌는가?”에 따라 선택이 갈립니다.

A. struct를 사용하는 경우

“데이터를 담는 용도”, 즉 값 중심 타입일 때.

  • DTO, Record, Value Object 등 단순한 데이터 전달 구조체
  • 알고리즘에서 사용하는 보조 구조 (Edge, Node, Point 등)
  • 공개 필드가 자연스러운 데이터형
struct Edge {
    int to;
    int cost;
};

struct Point {
    int x, y;
    double length() const noexcept {
        return std::sqrt(1.0 * x * x + 1.0 * y * y);
    }
};

📌 데이터가 중심이고, 캡슐화보단 직관성이 우선인 경우 적합합니다.


B. class를 사용하는 경우

“행동과 정책”, 즉 캡슐화 중심 타입일 때.

  • 내부 상태를 보호하고, 외부엔 인터페이스만 노출하고 싶을 때
  • 불변성, 유효성 검사, 비즈니스 로직 등이 필요한 경우
  • 수명/리소스 관리(RAII)나 상속, 다형성이 중요한 경우
class BankAccount {
public:
    explicit BankAccount(int initial);
    void deposit(int amount);
    void withdraw(int amount);
    int balance() const noexcept;

private:
    int balance_;
};

📌 데이터 보호, 정책 제어, 로직 관리가 목적이라면 class가 자연스럽습니다.


3. 유지보수성과 코드 스타일 팁

상황추천 키워드이유
데이터 구조, DTO, 레코드struct멤버가 공개되는 것이 자연스럽고 간단
도메인 로직, 상태 보유 객체class캡슐화 및 무결성 유지 용이
상속 기반 설계 (인터페이스 등)class접근 제어와 다형성 관리 명확
단순 데이터 묶음 + 연산자 오버로딩struct값 기반 표현에 적합

4. 실사용 예시로 이해하기

A. 데이터 중심 (알고리즘 보조 타입) — struct

struct Graph {
    int N{};
    std::vector<std::vector<int>> adj;
    std::vector<char> visited;

    explicit Graph(int n = 0)
        : N(n), adj(n + 1), visited(n + 1, 0) {}

    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    void bfs(int start) {
        std::queue<int> q;
        visited[start] = 1;
        q.push(start);

        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v : adj[u])
                if (!visited[v])
                    visited[v] = 1, q.push(v);
        }
    }
};

📌 데이터와 간단한 연산이 한 덩어리로 존재.
📌 필드 공개가 자연스럽고, 테스트도 간단.
따라서, struct 적합.


B. 정책 중심 (도메인 로직) — class

class GraphService {
public:
    explicit GraphService(int n) : N_(n), adj_(n + 1) {}

    void addEdge(int u, int v) {
        adj_[u].push_back(v);
        adj_[v].push_back(u);
    }

    int components() {
        std::vector<char> vis(N_ + 1, 0);
        int cnt = 0;
        for (int i = 1; i <= N_; ++i)
            if (!vis[i]) bfs(i, vis), ++cnt;
        return cnt;
    }

private:
    int N_;
    std::vector<std::vector<int>> adj_;

    void bfs(int s, std::vector<char>& vis) {
        std::queue<int> q; vis[s] = 1; q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v : adj_[u])
                if (!vis[v]) vis[v] = 1, q.push(v);
        }
    }
};

📌 내부 상태를 숨기고, 명확한 API로 관리.
따라서, 캡슐화 중심 → class 적합.


5. 자주 헷갈리는 오해 정리

오해진실
struct는 함수 정의 불가”❌ C++에선 가능. 생성자, 소멸자, 오버로딩, 상속 모두 지원
struct는 C 전용 문법”❌ C++에선 public class문법적 설탕(Syntactic Sugar)에 가깝습니다
“성능 차이가 있다”❌ 없습니다. 선택 기준은 오직 의도와 설계 철학입니다

📌 문법적 설탕(Syntactic Sugar)?
“이미 있는 기능을 더 간결하고 편하게 쓰도록 만든 문법”이라는 뜻입니다.
즉, 새로운 기능을 추가하는 건 아니고, 같은 기능을 더 보기 쉽게 표현한 문법적 편의를 말합니다.

예를 들어,
“설탕”이라는 말처럼 코드를 더 읽기 좋고 쓰기 쉽게 만드는 ‘감미료’ 같은 존재를 의미합니다. 내부적으로는 완전히 동일한 동작을 하지만, 개발자는 더 짧고 직관적인 코드를 쓸 수 있게 해줍니다.


6. C의 struct vs C++의 struct

CC++에서 struct라는 키워드는 같지만, 완전히 다른 목적과 철학을 가집니다.

C에서는 “데이터의 묶음”에 불과하지만, C++에서는 **“데이터 + 행동을 함께 표현하는 객체”** 로 발전했습니다.

항목C의 structC++의 struct
목적단순한 데이터 묶음 (메모리 레이아웃 중심)데이터 + 행동을 함께 표현하는 타입
멤버 함수❌ (불가)✅ (정의 가능)
생성자/소멸자
접근 제어❌ (전부 공개)✅ (public, private, protected)
상속/다형성
연산자 오버로딩
선언 방식struct Point p; 필수Point p; 가능
템플릿/네임스페이스

📌 한 줄 요약

  • C의 struct = 데이터 그릇
  • C++의 struct = 사실상 public class

A. 예시로 이해하기

C에서의 struct

// C 언어
#include <stdio.h>

struct Point {
    int x;
    int y;
};

// 함수는 구조체 밖에서 따로 정의
void move(struct Point* p, int dx, int dy) {
    p->x += dx;
    p->y += dy;
}

int main() {
    struct Point p = { 1, 2 };
    move(&p, 3, 4);
    printf("x = %d, y = %d\n", p.x, p.y);  // 출력: x = 4, y = 6
}

📌 C에서는

  • struct는 단순히 데이터 필드들의 묶음이며,
  • “행동”은 외부 함수로 분리됩니다.
  • 또한, struct 키워드를 생략할 수 없습니다. (struct Point p;)

즉, 구조체는 메모리 레이아웃(데이터의 집합) 자체를 표현합니다.


C++에서의 struct

// C++ 언어
#include <iostream>
#include <cmath>

struct Point {
    int x;
    int y;

    // 생성자
    Point(int x, int y) : x(x), y(y) {}

    // 멤버 함수
    void move(int dx, int dy) {
        x += dx;
        y += dy;
    }

    // 멤버 함수 (행동 + 상태)
    double length() const {
        return std::sqrt(1.0 * x * x + 1.0 * y * y);
    }
};

int main() {
    Point p{1, 2};      // struct 키워드 생략 가능
    p.move(3, 4);
    std::cout << p.x << ", " << p.y << " → length = " << p.length() << '\n';
}

📌 C++에서는

  • struct 안에 생성자, 멤버 함수, 연산자 모두 정의 가능하며,
  • 키워드 struct 없이 객체 생성 가능합니다.
  • 사실상 public class처럼 동작합니다.

B. 기술적 관점에서의 차이

관점CC++
언어 철학데이터 중심 (절차적)객체 중심 (캡슐화)
메모리 레이아웃단순 필드 나열동일하지만 접근제어자, 가상함수 등 추가 기능
함수 호출 방식move(&p, dx, dy)p.move(dx, dy) (객체 지향적)
코드 응집도낮음 (데이터와 함수 분리)높음 (데이터와 행동 결합)
확장성구조체마다 별도 함수 필요상속, 오버로딩 등 재사용 가능

즉,

C에서는 “데이터를 전달하기 위한 구조체”였던 것이,
C++에서는 “행동을 포함하는 객체”로 확장된 것입니다.


C. 요약 정리

  • Cstruct는 단순히 데이터 묶음이며, 함수는 외부에 존재합니다.
  • C++struct는 사실상 멤버가 public인 클래스로, 객체지향 기능을 모두 가집니다.
  • 따라서
    • C 스타일 구조체데이터 교환용(FFI, 바이너리 호환 등)
    • C++ 스타일 구조체데이터 중심 로직용(DTO, Record, POD) 으로 구분해 사용하면 좋습니다.

7. 자주 나오는 질문

Q1. struct에 private 멤버를 넣어도 되나요?

A. 네. C++에서는 접근제어자를 지원합니다. 단지 기본이 public일 뿐입니다.

Q2. 성능 차이는 전혀 없나요?

A. 없습니다. 메모리 구조나 실행 속도는 동일합니다. 선택은 “의도” 문제입니다.

Q3. 사용하는 기준이 다른가요?

A. 맞습니다. 보통 “데이터 중심은 struct, 로직 중심은 class로 정합니다.


결론: 의도를 드러내는 선택

  • C++에서 structclass문법적으로 거의 동일하지만, 기본 접근제한자와 상속제한자가 다릅니다.
  • 데이터 중심 타입struct
  • 로직/캡슐화 중심 타입class
  • Cstruct는 단순한 데이터 묶음, C++의 struct는 사실상 public class.

결국 중요한 건 “이 타입이 어떤 역할을 하는가” 입니다.
코드의 의도를 명확히 표현하는 선택이,
협업유지보수의 품질을 결정합니다.


한눈에 보는 요약 비교

구분struct (C++)class (C++)
기본 접근제한자publicprivate
기본 상속제한자publicprivate
멤버 함수 / 생성자 / 소멸자지원됨지원됨
상속 / 다형성지원됨지원됨
주요 용도데이터 중심 구조체 (Record, DTO, Point 등)캡슐화 중심 객체 (도메인 로직, 상태 관리 등)
profile
Why not change the code?

0개의 댓글