[TIL_C] 클래스

zehova
|2025. 8. 21. 21:08

Class는 C++에서 객체 지향 프로그래밍(OOP)의 핵심적인 개념으로, 객체를 만들기 위한 틀(blueprint) 또는 설계도 역할을 한다. 클래스는 데이터와 그 데이터를 다루는 함수를 하나의 단위로 묶어준다.

 

클래스의 구성 요소

클래스는 크게 두 가지로 구성됨.

  1. 멤버 변수 (Member Variables): 객체가 가지는 속성(상태)을 나타냅니다. 예를 들어, Car 클래스라면 color, speed 같은 변수들이 멤버 변수가 된다.
  2. 멤버 함수 (Member Functions): 객체가 할 수 있는 동작(행동)을 정의합니다. 예를 들어, Car 클래스라면 accelerate(), brake() 같은 함수들이 멤버 함수가 된다.

 

클래스와 객체의 차이

  • 클래스: 붕어빵을 만드는 '틀' 그 자체.
  • 객체 (Object): 그 틀로 찍어낸 실제 '붕어빵'.

클래스는 일종의 사용자 정의 자료형이며, 이 자료형을 이용해 메모리에 할당된 실체를 인스턴스(instance) 또는 객체라고 부른다. 하나의 클래스로 여러 개의 객체를 만들 수 있다.

 

클래스 사용 예시

#include <iostream>
#include <string>

// Car 클래스 정의
class Car {
public: // 접근 지정자: public은 외부에서 접근 가능
    // 멤버 변수
    std::string color;
    int speed;

    // 멤버 함수
    void accelerate() {
        speed += 10;
        std::cout << "가속! 현재 속도: " << speed << std::endl;
    }
    
    void brake() {
        if (speed >= 10) {
            speed -= 10;
        }
        std::cout << "감속! 현재 속도: " << speed << std::endl;
    }
};

int main() {
    // Car 클래스의 객체 생성
    Car myCar; 

    // 멤버 변수 초기화
    myCar.color = "Red";
    myCar.speed = 0;

    // 멤버 함수 호출
    myCar.accelerate(); // "가속! 현재 속도: 10" 출력
    myCar.accelerate(); // "가속! 현재 속도: 20" 출력
    myCar.brake();      // "감속! 현재 속도: 10" 출력
    
    return 0;
}

 

Car는 클래스이고, myCar는 Car 클래스로 만들어진 객체.

myCar는 color와 speed라는 속성을 가지며, accelerate()와 brake()라는 행동을 수행할 수 있다.

 

Getter와 Setter: 객체의 '문지기' 

Getter와 Setter는 클래스(객체)의 멤버 변수(속성)에 직접 접근하지 않고, 정해진 함수를 통해서만 접근하게 만드는 방법.

마치 중요한 정보가 들어있는 방에 문지기를 두는 것과 같다.

왜 사용하는가?

직접 변수에 접근하는 대신, 왜 굳이 함수(문지기)를 거쳐야 할까?

  1. 데이터 보호 (캡슐화): 멤버 변수의 값이 의도치 않게 변경되는 것을 막을 수 있다. 예를 들어, 나이를 나타내는 변수에 음수 값이 들어가는 것을 막고 싶을 때 setter 함수 안에서 유효성 검사를 할 수 있다.
  2. 유연성: 나중에 변수 이름을 바꾸더라도, getter와 setter 함수 이름은 그대로 유지할 수 있다. 이렇게 하면 변수 이름을 바꾸더라도 그 변수를 사용하는 다른 코드들을 수정할 필요가 없어서 편리하다.

 

1. Getter (정보를 '가져오는' 역할)

'Getter'는 멤버 변수에 저장된 값을 읽어오는 함수다. 보통 get이라는 접두사를 붙여서 만든다.

  • 역할: "이 방에 있는 나이가 몇 살인지 알려줘!"
int getAge() {
    return age;
}

 

 

2. Setter (정보를 '설정하는' 역할)

'Setter'는 멤버 변수의 값을 변경하는 함수다. 보통 set이라는 접두사를 붙여서 만든다.

  • 역할: "이 방에 있는 나이를 25살로 바꿔줘." (이때 25가 음수가 아닌지 검사할 수 있다.)
void setAge(int newAge) {
    if (newAge > 0) { // 유효성 검사
        age = newAge;
    }
}

 

 

[예시]

Person 클래스를 통해 직접 접근할 때와 getter/setter를 사용할 때의 차이를 비교

#include <iostream>

class Person {
private: // private은 외부에서 직접 접근 불가
    int age;

public:
    // Setter: 값을 설정하는 함수
    void setAge(int newAge) {
        if (newAge >= 0) { // 음수 나이를 막는 유효성 검사
            age = newAge;
        } else {
            std::cout << "나이는 음수가 될 수 없습니다." << std::endl;
        }
    }

    // Getter: 값을 읽어오는 함수
    int getAge() {
        return age;
    }
};

int main() {
    Person p;

    // Setter를 사용하여 안전하게 값 설정
    p.setAge(25);
    std::cout << "현재 나이: " << p.getAge() << std::endl; // 출력: 25

    // 유효하지 않은 값 설정 시도
    p.setAge(-10); // "나이는 음수가 될 수 없습니다." 출력
    std::cout << "변경 후 나이: " << p.getAge() << std::endl; // 출력: 25 (변경되지 않음)

    return 0;
}

 

 

 

공부하다 재복습한 부분: void

 

void는 C++에서 '비어 있음' 또는 '아무것도 없음'을 의미하는 특별한 키워드. 주로 두 가지 주요 용도로 사용된다.

1. 함수가 반환하는 값이 없을 때

함수를 정의할 때, void는 그 함수가 어떤 값도 반환하지 않는다는 것을 나타냄. 예를 들어, 화면에 메시지를 출력하는 함수는 계산 결과를 반환할 필요가 없다.

#include <iostream>

void sayHello() { // 반환 타입이 void
    std::cout << "안녕하세요!" << std::endl;
}

int main() {
    sayHello(); // 함수를 호출하지만, 반환되는 값이 없음
    return 0;
}

 

여기서 sayHello() 함수는 void를 반환 타입으로 사용하여 아무것도 반환하지 않음을 명시. 만약 int와 같은 다른 타입이었다면, return 문을 통해 해당 타입의 값을 반드시 반환해야 한다.

 

2. 함수가 인자를 받지 않을 때 (선택 사항)

함수가 어떤 인자도 받지 않는다는 것을 명확히 하고 싶을 때 void를 인자 목록에 사용하기도 한다.

C++에서는 인자 목록을 비워두는 것도 동일한 의미다.

// 두 가지 모두 동일한 의미를 가집니다.
void functionA();        // 인자 목록이 비어 있음
void functionB(void);  // void를 명시적으로 사용

 

이 두 함수는 모두 인자를 받지 않는다.

 

3. 기타 용도

void 포인터는 모든 종류의 데이터 포인터를 가리킬 수 있는 범용 포인터로 사용된다. 이 또한 void의 중요한 용도 중 하나.

 

요약하자면, void는 함수가 값을 반환하지 않거나 인자를 받지 않는다는 것을 명확하게 하기 위해 사용. 코드를 읽는 사람에게 함수의 역할을 더 쉽게 이해시키는 데 도움을 줌.