[DAY29] Test Recap(1) : struct, class, virtual function

베리투스·2025년 9월 12일

TIL: Today I Learned

목록 보기
30/93

오늘은 C++ 객체 지향 프로그래밍의 근간을 이루는 structclass, 그리고 다형성의 핵심인 가상 함수순수 가상 함수에 대한 이론을 깊이 파고들었다. 모의 면접과 테스트를 통해 어렴풋이 알던 개념들의 차이와 그 존재 이유를 명확히 이해하게 되었다. 특히 class의 기본 접근 지정자가 왜 private인지, 그리고 순수 가상 함수를 구현하지 않은 파생 클래스는 어떻게 되는지에 대한 개념을 바로잡을 수 있었던 의미 있는 하루였다.


📌 목표

  • structclass의 유일한 차이점과 관습적 사용법 이해하기
  • 가상 함수를 이용한 다형성(동적 바인딩)의 원리 파악하기
  • 순수 가상 함수와 추상 클래스의 개념 및 역할 정확히 알기
  • 테스트에서 틀렸던 '정보 은닉'과 '파생 클래스의 추상화' 개념 바로잡기

📖 이론

1. struct vs class: 투명한 상자 vs 안전한 금고

structclass의 유일한 문법적 차이는 '기본 접근 지정자'이다. struct는 멤버들이 기본적으로 public (공개) 상태이고, classprivate (비공개) 상태이다. 이 작은 차이가 두 키워드의 철학과 사용 목적을 완전히 갈라놓는다.

  • struct (투명한 상자 📦): 모든 내용물이 밖에서 훤히 보이는 투명한 상자와 같다. C언어 시절부터 내려온 개념으로, 여러 데이터를 단순히 하나로 묶어 관리하는 용도에 최적화되어 있다. 그래서 C++에서도 멤버 변수에 자유롭게 접근해야 하는 간단한 데이터 묶음, 즉 POD(Plain Old Data) 타입을 정의할 때 관습적으로 사용된다.

  • class (안전한 금고 🏦): 내용물(데이터)은 안에 안전하게 보관되고, 정해진 몇 개의 창구(public 메서드)를 통해서만 내용물에 접근할 수 있는 금고와 같다. 이는 객체 지향 프로그래밍의 핵심 원리인 캡슐화(Encapsulation)정보 은닉(Information Hiding)을 구현하기 위한 설계다. 데이터를 private으로 보호함으로써 외부에서 함부로 값을 바꾸는 것을 막고, 오직 클래스가 허용한 방식(public 함수)으로만 데이터가 조작되도록 보장한다. 이를 통해 객체의 일관성과 안정성을 높일 수 있다.

2. 가상 함수 vs 순수 가상 함수: 선택권 vs 의무

두 함수 모두 상속 관계에서 다형성(Polymorphism)을 구현하기 위해 사용되지만, 파생 클래스에게 주는 메시지가 다르다.

  • 가상 함수 (virtual): "재정의해도 좋고, 안 해도 괜찮아" (선택권 부여)
    가상 함수는 기반 클래스의 포인터나 참조를 통해 파생 클래스의 객체를 가리킬 때, 포인터의 타입이 아닌 실제 객체의 타입에 맞는 함수를 호출하게 해주는 마법 같은 기능이다. 이를 동적 바인딩(Dynamic Binding)이라고 한다. 컴파일 시점이 아닌, 프로그램 실행 시점(런타임)에 호출될 함수가 결정되는 것이다. 기반 클래스는 virtual 키워드를 통해 "이 함수는 후손 클래스가 자신만의 방식으로 바꿀 수 있는 기능이야"라고 알려주는 역할을 한다. 파생 클래스는 이 함수를 재정의(override)해서 자신만의 동작을 구현할 수도 있고, 그냥 부모의 기능을 그대로 물려받아 사용할 수도 있다.

  • 순수 가상 함수 (virtual ... = 0;): "반드시 재정의해야만 해!" (의무 부여)
    순수 가상 함수는 이름만 있고 실제 구현(몸체)은 없는, 말 그대로 '순수한' 함수 선언이다. 이 함수를 하나라도 가진 클래스는 추상 클래스(Abstract Class)가 되며, 설계도와 같은 존재가 된다. 추상 클래스는 미완성된 설계도이기 때문에 그 자체로 객체(제품)를 만들 수 없다.
    추상 클래스의 역할은 파생 클래스들에게 "나를 상속받으려면, 내가 정의한 이 순수 가상 함수들을 반드시 너희들만의 방식으로 구현해야 한다"강력한 계약(Contract) 또는 인터페이스(Interface)를 제시하는 것이다. 만약 파생 클래스가 이 의무를 다하지 않고 순수 가상 함수를 구현하지 않으면, 그 파생 클래스 역시 미완성 설계도, 즉 또 다른 추상 클래스가 되어버린다.


⚠️ 실수

  • 접근 지정자(private)와 상수성(const) 혼동: classprivate 멤버에 직접 접근하려 할 때 발생하는 컴파일 에러의 원인을 값이 변하지 않는 const 때문이라고 순간 착각했다. private는 클래스 외부에서의 접근 권한을 막는 '정보 은닉'의 개념이고, const는 변수의 값 변경을 막는 '상수성'의 개념이다. 둘은 완전히 다른 목적을 가진다는 것을 명심해야 한다.
  • 순수 가상 함수를 구현하지 않은 파생 클래스의 운명: 추상 클래스를 상속받은 파생 클래스가 순수 가상 함수를 구현하지 않으면, 그 즉시 컴파일 에러가 발생하는 줄 알았다. 하지만 실제로는 '그 파생 클래스 또한 추상 클래스가 되는 것'이 정답이었다. 따라서 클래스 선언 자체는 문제가 없지만, 그 클래스로 객체를 생성하려고 할 때 컴파일 에러가 발생한다. 미묘하지만 아주 중요한 차이점이다.

✅ 핵심 요약

개념설명비고
struct기본 접근 지정자가 public인 사용자 정의 타입주로 간단한 데이터 묶음에 사용 (POD)
class기본 접근 지정자가 private인 사용자 정의 타입객체 지향 프로그래밍의 캡슐화, 정보 은닉에 사용
가상 함수virtual 키워드로 선언. 동적 바인딩을 통해 다형성 구현.파생 클래스에서 선택적으로 재정의(override) 가능
순수 가상 함수virtual ... = 0;으로 선언. 함수의 구현부가 없음.파생 클래스에서 반드시 재정의해야 객체 생성 가능
추상 클래스순수 가상 함수를 하나 이상 포함하는 클래스.객체를 직접 생성할 수 없으며, 인터페이스 역할 수행
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글