언리얼 엔진/개념 정리

개념 정리 - C++(클래스)

journey46110 2026. 7. 10. 20:27

클래스 (Class)

1) 클래스가 필요한 이유

클래스가 없을 때의 예시 - 학생의 성적을 관리하는 프로그램

int korean = 90;
int english = 80;
int math = 100;

float GetAverage(int kor, int eng, int math);
int GetMax(int kor, int eng, int math);

과목 추가 -> 함수의 매개 변수 수정 필요
학생이 여러 명 -> 변수가 많아짐

점수를 아무 곳에서나 수정할 수 있음

- 데이터와 기능이 따로 놀기 때문에 유지보수가 어려움

 

 

2) 클래스의 정의

- 관련된 데이터(변수)와 기능(함수)을 하나로 묶어 놓은 설계도

- 클래스를 호출할 때 세부사항은 몰라도 되고, 기능만 이해하고 작동하면 됨

 

 

3) 클래스의 구성

class Student
{
private:
    int korean;
    int english;
    int math;

public:
    float GetAverage();
    int GetMaxScore();
};

 

① 멤버 변수 (Member Variable)

- 데이터

int korean;
int english;
int math;

 

② 멤버 함수 (Member Function)

- 동작

GetAverage();
GetMaxScore();

 

 

4) 객체 (Object)

- 클래스는 설계도에 해당함

Student s1;
Student s2;
Student s3;

- 실제로 사용하는 것은 이렇게 만든 객체임

 

 

5) 멤버 접근 연산자 (.)

- 객체 안의 변수나 함수는 . 으로 접근함

Student s;

s.GetAverage();

 

 

6) 접근 제어자

① public

- 누구나 접근 가능함

public:
    void Print();

 

② private

- 클래스 내부에서만 접근 가능함

- 아무 곳에서나 변수를 수정할 수 있으면 프로그램이 망가짐

- 직접 수정은 막고 함수를 통해서만 수정할 수 있게 함

private:
    int score;
Student s;

s.score = 100; //에러 발생

 

 

7) Getter / Setter

① Getter

- 값을 가져오는 함수

int GetScore()
{
    return score;
}

 

② Setter

- 값을 변경하는 함수

- 보통 검사를 같이 함

void SetScore(int s)
{
    if(s >= 0 && s <= 100)
        score = s;
}

- private를 사용하는 가장 큰 이유

 

 

8) 생성자 (Constructor)

- 객체가 만들어질 때 자동으로 호출되는 함수

 

① 자동으로 호출되는 함수

- 반환형이 없음

- 이름이 클래스와 같음

Student()
{
}

 

② 기본 생성자

- 자동 호출

Student()
{
    score = 0;
}

Student s;

 

③ 매개변수 생성자

- 매개변수를 받음

- 매개변수를 지정하지 않으면 에러가 발생함

Student(int s)
{
    score = s;
}

Student s(100);

 

④ 기본값 생성자

- 매개변수를 지정하지 않으면 기본값이 설정됨

Student(int s = 100)
{
    score = s;
}

Student s1;
Student s2(50);

 

 

9) 클래스 내부 구현과 외부 구현

① 내부 구현

- 간단한 함수에 적합함

- 함수를 클래스 내부에서 구현함

class Student
{
public:

    void Print()
    {
        cout << "Hello";
    }
};

 

② 외부 구현

- 헤더(.h)와 cpp를 분리하고, cpp에서 함수를 구현함

- 실무에서 대부분 사용하는 방식임

헤더 파일

class Student
{
public:
    void Print();
};

 

cpp 파일

#include "Student.h"

void Student::Print()
{
    cout << "Hello";
}

 

main 함수

#include "Student.h"

int main()
{
    Student s;
    s.Print();
}

 

 

10) include Guard

- 헤더가 여러 번 include되는 것을 막음

- 한 번 정의하는 과정을 거친 클래스는 다음에 정의하는 과정을 무시함

#ifndef STUDENT_H
#define STUDENT_H

class Student
{
};

#endif

 

 

11) 클래스의 특성

① 캡슐화

- 데이터와 기능을 하나로 묶음

Student
├── score
├── name
├── GetAverage()
└── Print()

 

② 정보 은닉

- 필요한 것만 공개함

public
↓
사용 가능

private
↓
숨김

 

③ 재사용성

- 한 번 만든 클래스를 여러 번 사용할 수 있음

Student a;
Student b;
Student c;
Student d;

 

④ 유지보수성

- 기능을 수정해도 클래스를 사용하는 코드는 거의 수정하지 않음

 

 

11) 배터리 관리 클래스 만들기

① 기본값을 가진 생성자 만들기

- 배터리 잔량의 기본값은 100

- 0보다 작은 숫자와 100보다 큰 숫자의 예외처리를 함

Battery(int initialCharge = 100) {
    charge = initialCharge;

    if (charge < 0) {
        charge = 0;
    }
    else if (charge > 100) {
        charge = 100;
    }

 

② 배터리 잔량을 반환하는 함수

 int getCharge() const {
     return charge;
 }

 

③ 배터리를 사용하는 함수

- 한 번 사용할 때마다 5씩 감소함

 void useBattery() {
     if (charge >= 5) {
         charge -= 5;
     }
     else {
         charge = 0;
     }
     std::cout << "Battery used. Current charge: " << charge << "%\n";
 }

 

④ 배터리를 충전하는 함수

- 한 번 충전할 때마다 7씩 증가함

void chargeBattery() {
    if (charge <= 93) {
        charge += 7;
    }
    else {
        charge = 100;
    }
    std::cout << "Battery charged. Current charge: " << charge << "%\n";
}

 

⑤ 코드 예시

#include <iostream>

class Battery {
private:
    int charge; // 배터리 잔량

public:
    // 생성자: 기본값은 100으로 설정
    Battery(int initialCharge = 100) {
        charge = initialCharge;

        if (charge < 0) {
            charge = 0;
        }
        else if (charge > 100) {
            charge = 100;
        }
    }

    // 배터리 잔량 반환
    int getCharge() const {
        return charge;
    }

    // 배터리를 사용하여 잔량 감소
    void useBattery() {
        if (charge >= 5) {
            charge -= 5;
        }
        else {
            charge = 0;
        }
        std::cout << "Battery used. Current charge: " << charge << "%\n";
    }

    // 배터리를 충전하여 잔량 증가
    void chargeBattery() {
        if (charge <= 93) {
            charge += 7;
        }
        else {
            charge = 100;
        }
        std::cout << "Battery charged. Current charge: " << charge << "%\n";
    }
};

void usingbattery() {
    // 배터리 객체 생성 (초기 잔량 100)
    Battery battery;

    std::cout << "Initial charge: " << battery.getCharge() << "%\n";

    // 배터리 사용 및 충전 테스트
    battery.useBattery(); // 잔량 95%
    battery.useBattery(); // 잔량 90%
    battery.chargeBattery(); // 잔량 97%
    battery.useBattery(); // 잔량 92%
}

 

 

12) 두 분수의 곱셉을 할 수 있는 클래스 만들기

① 기본값을 가진 생성자 만들기

- 분자의 기본값은 0, 분모의 기본값은 1임

- 분모에 0이 들어오면 1로 바꿔줌

Fraction(int num = 0, int denom = 1) {
    numerator = num;
    denominator = (denom != 0) ? denom : 1; // 분모가 0이면 1로 설정
}

 

② 유클리드 호제법으로 최대공약수를 구하는 함수

int gcd(int a, int b) const {
    while (b != 0) {
        int temp = b; // 현재 b 값을 저장
        b = a % b;    // a를 b로 나눈 나머지를 새로운 b로 설정
        a = temp;     // 이전 b 값을 새로운 a로 설정
    }
    return a; // b가 0이 되었을 때 a가 최대공약수
}

 

③ 최대공약수를 이용해 분수를 기약분수로 바꿔주는 함수

void simplify() {
    int gcdValue = gcd(numerator, denominator); // 분자와 분모의 최대공약수 계산
    numerator /= gcdValue;   // 분자를 최대공약수로 나누기
    denominator /= gcdValue; // 분모를 최대공약수로 나누기
}

 

④ 두 분수를 곱하는 함수

Fraction multiply(const Fraction& other) const {
    // 새로운 분자 = 현재 분수의 분자 * 다른 분수의 분자
    int newNumerator = numerator * other.numerator;

    // 새로운 분모 = 현재 분수의 분모 * 다른 분수의 분모
    int newDenominator = denominator * other.denominator;

    // 새로운 Fraction 객체 생성
    Fraction result(newNumerator, newDenominator);

    // 결과를 간단히 만들기
    result.simplify();

    return result;
}

 

⑤ 분수를 출력하는 함수

void display() const {
    cout << numerator << "/" << denominator;
}

 

⑥ 코드 예시

#include <iostream>
using namespace std;

// Fraction 클래스 정의
// 분수를 표현하고 곱셈 및 단순화 기능을 제공합니다.
class Fraction {
private:
    int numerator;   // 분자
    int denominator; // 분모

    // 최대공약수를 계산하는 유클리드 호제법 구현
    // gcd 함수는 Fraction 클래스 내부에서만 사용되므로 private으로 설정
    int gcd(int a, int b) const {
        while (b != 0) {
            int temp = b; // 현재 b 값을 저장
            b = a % b;    // a를 b로 나눈 나머지를 새로운 b로 설정
            a = temp;     // 이전 b 값을 새로운 a로 설정
        }
        return a; // b가 0이 되었을 때 a가 최대공약수
    }

public:
    // 매개변수가 있는 생성자
    // 사용자로부터 분자와 분모를 입력받아 초기화합니다.
    // 분모가 0일 경우 자동으로 1로 설정합니다. (분모가 0이면 정의되지 않음)
    Fraction(int num = 0, int denom = 1) {
        numerator = num;
        denominator = (denom != 0) ? denom : 1; // 분모가 0이면 1로 설정
    }

    // 분수를 간단한 형태로 변환하는 함수
    // 최대공약수(gcd)를 이용해 분자와 분모를 나눕니다.
    void simplify() {
        int gcdValue = gcd(numerator, denominator); // 분자와 분모의 최대공약수 계산
        numerator /= gcdValue;   // 분자를 최대공약수로 나누기
        denominator /= gcdValue; // 분모를 최대공약수로 나누기
    }

    // 두 분수를 곱하는 함수
    // 두 분수를 곱한 새로운 분수를 반환합니다.
    Fraction multiply(const Fraction& other) const {
        // 새로운 분자 = 현재 분수의 분자 * 다른 분수의 분자
        int newNumerator = numerator * other.numerator;

        // 새로운 분모 = 현재 분수의 분모 * 다른 분수의 분모
        int newDenominator = denominator * other.denominator;

        // 새로운 Fraction 객체 생성
        Fraction result(newNumerator, newDenominator);

        // 결과를 간단히 만들기
        result.simplify();

        return result;
    }

    // 분수를 출력하는 함수
    // 분자를 '/' 기호와 함께 출력합니다.
    void display() const {
        cout << numerator << "/" << denominator;
    }
};

void fraction(void) {
    // 두 분수 생성
    Fraction f1(1, 2); // 첫 번째 분수: 1/2
    Fraction f2(3, 4); // 두 번째 분수: 3/4

    // 두 분수를 곱하기
    Fraction product = f1.multiply(f2); // f1 * f2

    // 결과 출력
    cout << "곱한 결과: ";
    product.display(); // 결과 분수 출력
    cout << endl;
}