[Day10] Classes & OOP(Object-Oriented Programming)

베리투스·2025년 8월 18일

TIL: Today I Learned

목록 보기
18/93

C++ 객체지향 프로그래밍의 핵심인 class에 대해 학습했다. 관련 데이터와 함수를 하나로 묶어 코드의 재사용성유지보수성을 높이는 방법을 배웠다. 💻 public, private 접근 제어자를 통한 캡슐화, 생성자를 이용한 객체 초기화, getter와 setter를 통한 안전한 데이터 관리법을 익혔다. 마지막으로 클래스 선언부와 구현부를 .h.cpp 파일로 분리하여 체계적인 프로젝트를 구성하는 방법까지 정리했다. 🚀


📌 목표

  • 클래스의 역할과 필요성 이해
  • 클래스와 객체를 정의하고 활용
  • 접근 제어자(public, private)를 사용한 캡슐화
  • 생성자, getter, setter의 개념과 사용법 학습
  • 헤더(.h)와 소스(.cpp) 파일 분리

📖 이론

1. 클래스(Class)의 등장 배경

  • 기존의 절차지향 프로그래밍에서는 데이터(변수)와 그 데이터를 처리하는 함수가 분리되어 있었다.
  • 이로 인해 프로그램의 규모가 커질수록 데이터와 함수 간의 관계가 복잡해지고, 데이터가 의도치 않게 변경될 위험이 있었다. (예: 성적 관리 프로그램에서 국어, 영어, 수학 점수 배열과 평균 계산 함수가 따로 노는 경우)
  • 클래스는 이러한 문제를 해결하기 위해 관련 있는 데이터와 함수를 하나의 묶음으로 정의하는 방법을 제공했다.

2. 클래스의 정의와 캡슐화

  • 클래스(Class): 객체를 생성하기 위한 '설계도' 또는 '틀'이다. 클래스 내부에는 데이터 저장을 위한 멤버 변수(Member Variables)와 특정 동작을 수행하는 멤버 함수(Member Functions)가 포함된다.
  • 캡슐화(Encapsulation): 클래스의 핵심 특징 중 하나로, 데이터(멤버 변수)와 해당 데이터를 처리하는 함수를 하나로 묶고, 외부로부터의 직접적인 접근을 제한하여 데이터를 보호하는 것을 의미한다. 마치 자동차의 내부 엔진은 숨기고 운전자에게는 핸들과 페달만 제공하는 것과 같다.

3. 접근 제어자(Access Specifiers)

  • 캡슐화를 구현하기 위해 사용하며, 멤버에 대한 외부 접근 수준을 지정한다.
    • public: 클래스 외부 어디에서든 접근할 수 있다. 주로 멤버 함수(메서드)에 사용된다.
    • private: 해당 클래스의 멤버 함수 내에서만 접근할 수 있다. 외부에서는 절대 접근할 수 없으며, 정보 은닉(Information Hiding)을 실현한다. 멤버 변수는 보통 private으로 선언한다.
    • (참고) class 키워드로 클래스를 정의할 때, 접근 제어자를 명시하지 않으면 모든 멤버는 기본적으로 private이 된다.

4. getter와 setter

  • private으로 선언된 멤버 변수는 외부에서 직접 접근할 수 없기 때문에, 이 변수의 값을 읽거나 수정할 수 있는 통로가 필요하다.
    • getter: private 멤버 변수의 값을 읽어서 반환하는 public 멤버 함수. (e.g., int getScore();)
    • setter: private 멤버 변수의 값을 설정(수정)하는 public 멤버 함수. (e.g., void setScore(int newScore);)
    • 이를 통해 데이터의 무결성을 검사하는 로직(e.g., 점수는 0~100 사이)을 setter 내부에 추가할 수 있어, 데이터를 안전하게 관리할 수 있다.

5. 생성자(Constructor)

  • 객체가 생성될 때 자동으로 호출되는 특별한 멤버 함수이다.
  • 주로 멤버 변수를 초기화하는 역할을 한다.
  • 클래스 이름과 동일한 이름을 가지며, 반환형이 없다.
  • 매개변수가 없는 기본 생성자와 매개변수를 통해 값을 전달받는 매개변수 있는 생성자가 있다.

6. 헤더(.h)와 소스(.cpp) 파일 분리

  • 프로젝트 규모가 커지면 하나의 파일에 모든 코드를 작성하기 어렵다.
  • 헤더 파일(.h): 클래스의 선언부를 작성한다. 클래스의 구조, 멤버 변수, 멤버 함수의 원형(prototype) 등이 포함된다. 다른 파일에서 이 클래스를 사용하려면 이 헤더 파일을 #include한다.
  • 소스 파일(.cpp): 클래스의 구현부를 작성한다. 헤더 파일에 선언된 멤버 함수들의 실제 동작 코드를 정의한다.
  • 헤더 가드(Header Guard): 헤더 파일이 여러 번 #include되어 발생하는 중복 정의 오류를 막기 위해 #ifndef, #define, #endif 전처리기 지시문을 사용한다.

💻 코드

Student.h (클래스 선언부)

// 헤더 가드: STUDENT_H_가 정의되지 않았다면 아래 코드를 컴파일
#ifndef STUDENT_H_
// STUDENT_H_를 정의. 다음에 이 파일을 또 include하면 위 ifndef에 걸려 코드가 무시됨
#define STUDENT_H_

// Student 클래스 선언
class Student {
public: // 외부에서 접근 가능한 멤버
    // 생성자: 객체 생성 시 점수를 받아 초기화 (기본값 할당)
    Student(int math = 0, int eng = 0, int kor = 0);

    // 멤버 함수(메서드) 선언
    double getAvg();      // 평균 점수를 반환하는 getter
    int getMaxScore();  // 최고 점수를 반환하는 getter

private: // 클래스 내부에서만 접근 가능한 멤버
    // 멤버 변수: 학생의 과목별 점수
    int kor;
    int eng;
    int math;
};

#endif // 헤더 가드 끝

Student.cpp (클래스 구현부)

#include "Student.h" // Student 클래스 선언이 담긴 헤더 파일을 포함
#include <algorithm> // std::max 함수를 사용하기 위해 포함

// 생성자 구현
// Student 클래스에 속한 생성자임을 ::(스코프 지정 연산자)로 명시
// 멤버 초기화 리스트를 사용하여 멤버 변수 초기화
Student::Student(int math, int eng, int kor) : math(math), eng(eng), kor(kor) {
    // 생성자 본문은 비워둘 수 있음
}

// getAvg 멤버 함수 구현
double Student::getAvg() {
    // private 멤버 변수인 kor, eng, math에 접근하여 평균 계산
    return (kor + eng + math) / 3.0;
}

// getMaxScore 멤버 함수 구현
int Student::getMaxScore() {
    // std::max를 중첩 사용하여 세 과목 중 최고 점수 반환
    return std::max(kor, std::max(eng, math));
}

main.cpp (클래스 사용부)

#include <iostream>
#include "Student.h" // 우리가 정의한 Student 클래스를 사용하기 위해 include

int main() {
    // Student 클래스의 객체(인스턴스) 생성
    // 생성자에 인자를 전달하여 각 과목 점수 초기화
    Student student1(90, 85, 95);

    // 객체의 public 멤버 함수 호출
    std::cout << "학생1의 평균 점수: " << student1.getAvg() << std::endl;
    std::cout << "학생1의 최고 점수: " << student1.getMaxScore() << std::endl;

    // student1.kor = 100; // 컴파일 에러! kor은 private 멤버이므로 외부에서 직접 접근 불가

    return 0;
}

⚠️ 실수

  • 처음에는 main.cpp에서 "Student.h"include하는 것을 잊어서 Student 타입을 찾을 수 없다는 에러를 만났다. 😅 클래스를 사용하려면 반드시 그 설계도(헤더 파일)를 포함시켜야 한다는 것을 깨달았다.
  • Student.cpp에서 멤버 함수를 구현할 때 Student:: 스코프 지정자를 빼먹어서 "정의되지 않은 함수"라는 컴파일 오류를 겪었다. 어떤 클래스에 속한 함수인지 명확히 알려줘야 한다는 점을 명심해야겠다.
  • #include <iostream>#include "Student.h"의 차이도 헷갈렸는데, <>는 시스템 라이브러리 헤더를, ""는 사용자 정의 헤더를 우선적으로 찾는다는 점을 되새겼다.

✅ 핵심 요약

개념설명비고
클래스 (Class)객체를 만들기 위한 설계도. 데이터(멤버 변수)와 기능(멤버 함수)을 하나로 묶는다.class Student { ... };
객체 (Object)클래스라는 설계도를 바탕으로 메모리에 실체화된 인스턴스.Student student1;
캡슐화데이터와 함수를 묶고, 외부의 직접적인 접근을 막아 정보를 은닉하는 것.객체지향의 핵심 원칙
접근 제어자public, private 등을 사용하여 멤버의 접근 권한을 제어한다.public: 외부 공개, private: 내부 전용
생성자객체가 생성될 때 자동으로 호출되어 멤버 변수를 초기화하는 특별한 함수.클래스 이름과 동일, 반환형 없음
getter & setterprivate 멤버에 안전하게 접근(읽기/쓰기)하기 위해 제공되는 public 함수.데이터 무결성 유지에 유용
파일 분리클래스의 선언은 헤더(.h)에, 구현은 소스(.cpp)에 작성하여 코드의 구조화 및 재사용성을 높인다.헤더 가드(#ifndef) 필수
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글