객체 지향 프로그래밍 (OOP), C++ 기반

변재현 (Jaehyun Byun)·2025년 7월 18일
0

Computer Science

목록 보기
2/6
post-thumbnail

자료구조 & 알고리즘 시리즈

1. 프로그래밍 입문과 C++ 기본 문법

우리가 살아가는 현실 세계는 수많은 객체들로 구성되어 있습니다. 고양이는 울고, 사람은 걷고, 자동차는 달립니다. 객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 이런 현실 세계의 구조를 그대로 본떠 만든 프로그래밍 방식입니다. 프로그램을 하나의 거대한 절차가 아닌 독립적인 객체들의 협력으로 구성함으로써 더 직관적이고 유지보수하기 쉬운 코드를 만들 수 있습니다.

1. 객체 지향이란?

객체지향 프로그래밍(OOP)은 현실 세계의 구조를 본떠 만든 프로그래밍 방식입니다. 우리가 사는 세상이 사람, 자동차, 고양이처럼 객체로 구성되어 있듯이, 객체지향도 프로그램을 객체 단위로 나누어 설계합니다.

  • 객체(Object): 속성과 기능을 모두 포함하는 단위
    (예: 고양이 → 나이, 색상 + 울기, 걷기)
  • 클래스(Class): 객체를 만들기 위한 설계도
class Circle {
public:
    int radius;  // 원의 반지름 (속성)

    int calcArea() {  // 원의 면적을 계산하는 기능
        return 3.14 * radius * radius;  // 원의 면적 공식 πr²
    }
};

Circle이라는 클래스(설계도)를 정의하여 radius라는 속성(데이터)과 calcArea()라는 기능(메서드)을 가진 객체(Object)를 만들 수 있습니다.

⚠️ 주의: 클래스는 단순한 변수 묶음이 아니라 기능(함수)까지 포함합니다.

2. 인터페이스와 클래스 분리 구현

C++에서 프로그램이 점점 커지고 복잡해질수록, 클래스의 선언(인터페이스)구현(기능)분리해서 관리하는 것이 중요합니다. 이렇게 하면 코드를 더 읽기 쉽게 만들고 수정하거나 유지보수할 때 실수 가능성을 줄일 수 있습니다.

  • 헤더 파일(.h): 클래스의 인터페이스 (변수와 함수 원형 선언)
  • 소스 파일(.cpp): 클래스의 기능 구현

C++에서는 이를 위해 위와 같은 확장자를 사용합니다.

// Circle.h
class Circle {
public:
    Circle(double r);       // 생성자 선언
    double calcArea();      // 면적 계산 함수 선언
private:
    double radius;          // 반지름 저장 변수
};

// Circle.cpp
#include "Circle.h"
#include <cmath>

Circle::Circle(double r) : radius(r) {}  // 생성자 정의 (초기화 리스트 사용)
double Circle::calcArea() {
    return M_PI * radius * radius;       // cmath의 PI 사용해 면적 계산
}

클래스를 설계할 때는 위처럼 헤더(.h)에 인터페이스, 소스(.cpp)에 구현을 나눠서 작성하는 것이 좋은 습관입니다.

⚠️ 주의: 헤더 파일에는 함수의 정의가 아니라 선언만 작성해야 합니다. 구현까지 써버리면 중복 정의 오류가 발생할 수 있습니다.
⚠️ 주의: 헤더 파일은 #ifndef, #define, #endif 전처리기를 이용해 중복 포함을 방지해야 합니다.
⚠️ 주의: .cpp 파일에는 반드시 해당 클래스의 헤더 파일을 #include 해야 합니다.

3. 생성자, 소멸자, 접근자, 설정자

C++에서 객체지향 프로그래밍(OOP)의 핵심은 객체의 상태(데이터)를 안전하게 관리하고 객체의 생성과 소멸 과정을 명확히 제어하는 것입니다. 이때 사용하는 중요한 함수들이 바로 생성자, 소멸자, 그리고 접근자/설정자입니다.

  • 생성자(Constructor): 객체 생성 시 자동 실행되어 변수 초기화
  • 소멸자(Destructor): 객체 소멸 시 자동 실행되어 정리 작업 수행
#include <iostream>
using namespace std;

class Student {
private:
    string name;  // 이름 (외부에서 직접 접근 불가)
    int age;      // 나이

public:
    // 생성자
    Student(string n, int a) {
        name = n;
        setAge(a);  // setter 통해 유효성 검사
    }

    // 소멸자
    ~Student() {
        cout << "학생 객체가 삭제됩니다: " << name << endl;
    }

    // 정보 출력 함수
    void displayInfo() {
        cout << "이름: " << name << ", 나이: " << age << endl;
    }

    // Setter (나이 설정)
    void setAge(int a) {
        if (a >= 0) age = a;
        else cout << "⚠️ 나이는 0 이상이어야 합니다!" << endl;
    }

    // Getter (나이 조회)
    int getAge() const {
        return age;
    }
};

3.1 생성자(Constructor)

Student(std::string n, int a);
  • 정의: 객체가 생성될 때 자동으로 호출되는 특수한 함수.
  • 역할: 객체의 초기 상태 설정 (예: 멤버 변수 초기화).
  • 이름: 클래스 이름과 같고, 반환형이 없다.

생성자는 Student s("Alice", 20); 처럼 객체를 만들 때 자동 실행되며, name = "Alice", age = 20으로 초기화합니다.

3.2 소멸자(Destructor)

~Student();
  • 정의: 객체가 소멸될 때 자동 호출되는 함수.
  • 역할: 정리 작업 수행 (예: 동적 메모리 해제, 로그 출력 등).
  • 이름: 클래스 이름 앞에 ~ 붙이며, 매개변수나 반환형 없음.

프로그램 종료 시나 delete 명령으로 객체가 삭제될 때 실행됩니다. 디버깅용 메시지를 출력하거나 자원을 해제하는 데 유용합니다.

3.3 접근자(Getter)와 설정자(Setter)

객체 내부 데이터를 외부에서 직접 수정하지 못하도록 보호(private)하고, 대신 공식적인 함수로 간접 접근하게 하는 방식입니다.

  • 외부에서 멤버 변수를 마음대로 바꾸는 걸 막고, 데이터 무결성을 보장하기 위해 사용합니다.
  • 특히 age나 score처럼 잘못된 값(음수 등)이 들어오면 안 되는 경우 필수입니다.

💡 Tip: 캡슐화(Encapsulation)
이런 식으로 데이터를 외부로부터 보호하고, 공식적인 함수만으로 제어하는 것을 캡슐화라고 합니다.

0개의 댓글