Day 9

Kyu_·4일 전

Unreal 본캠프

목록 보기
9/12

게임 개발자를 위한 C++ 문법

템플릿

함수 오버로딩

  • C++에서는 함수 이름과 매개변수 타입 정보를 함께 사용해 함수를 구분한다.
  • 함수 이름 구분을 위해 내부적으로 고유한 이름을 부여하는것을 네임 맹글링이라고 한다.
  • 함수이름이 같고 -> 매개변수 타입이 다른경우, 매개변수의 개수가 다른경우 오버로딩

오버로딩이 안되는 경우

  • 타입 변환이 가능한 매개변수로 인해 두 개 이상의 오버로딩된 함수가 호출 후보가 되는 경우
  • 디폴트 매개변수로 인해 함수 호출 형태가 중복되는 경우
  • 매개변수의 타입만 포인터와 배열로 다른 경우
  • 함수의 반환 타입만 다른 경우

오버로딩의 순서

  • 정확한 매개변수 타입 일치

  • 타입 승격 변환 : 값이 손실되지 않는 방향으로 변환하는것을 승격이라고 함

    • char or short -> int
    • float -> double
    • bool -> int
  • 표준 타입 변환 : 승격보다는 광범위, 값 손실이 발생하는 경우도 있다.

    • int -> double
    • double -> int
    • double -> float
  • 사용자 정의 타입 변환 : 클래스 타입의 변환 함수나 생성자 등을 통해 이뤄지는 변환

템플릿

  • 타입에 관계없이 일반화된 코드를 작성하기 위한 문법
  • template
  • 어떤 타입이 올지 모르나 그 타입을 T로 부르겠다.

템플릿 클래스

함수 뿐아니라 클래스도 템플릿으로 사용해 일반화할 수 있습니다.

숙제

STL 기초

STL은 C++ 표준 라이브러리의 일부로, 컨테이너, 알고리즘, 반복자 등의 템플릿 기반 구성 요소를 포함합니다.

컨테이너

  • 데이터를 담는 자료구조를 말함
  1. 모든 컨테이너는 템플리승로 구현되어 있으므로, 다양한 타입의 데이터를 저장할 수 있습니다.
  2. 모든 컨테이너는 메모리 관리를 내부적으로 합니다. 따라서 사용 시 메모리 해제를 직접 고려하지 않아도 됩니다.
  3. 대부분 컨테이너는 반복자를 제공, 따라서 내부 구현을 몰라도 동일한 방식으로 컨테이너를 순회할 수 있습니다.

벡터

  • 벡터는 배열과 매우 유사한 컨테이너
  1. 템플릿 클래스로 구현되어 특정 타입에 종속되지 않음
  2. 삽입되는 원소 개수에 따라 내부 배열의 크기가 자동으로 조정
  3. 임의 접근이 가능(인덱스를 통해 특정 위치에 접근)
  4. 삽입/삭제는 맨 뒤에 하는 게 좋습니다. (중간 삽입/삭제는 배열 복사가 필요하므로 비효율적)
  • 벡터 복사
vector<int> vec3 = {1, 2, 3, 4, 5};
vector<int> vec4(vec3);
//vector<int> vec4 = vec3 하면 대입
  • 2차원 배열처럼 벡터 사용, 벡터의 타입을 벡터로 하면 된다.
vector<vector<int>> vec2D(3, vector<int>(4, 7)); // 3x4행렬, 모든 원소가 7로 초기화
  • erase
// 두 번째 요소 제거
vec.erase(vec.begin() + 1);

// 2~4 번째 요소 제거
vec.erase(vec.begin()+1, vec.begin()+3);

  • 키-값 쌍 형태로 저장
  • 키값을 기준으로 오름차순 자동 정렬
  • 중복된 키값 허용 X
myMap[5] = "Apple";
myMap.insert(make_pair(1, "Banana"));
myMap.insert({2, "Orange"});
  • insert()와 make_pair()를 함쎄 사용해서 값 추가 가능

  • {}나 []로 추가도 가능

  • find() : 특정 key가 map에 존재하는지 확인가능

  • size() : 키-값 쌍의 개수를 반환

  • erase(key) : 특정key를 가진 요소 삭제, 삭제된 요소의 개수를 반환하는데 map은 키중복이 안되므로 삭제 성공하면 1, 실패하면 0이 반환된다.

  • myMap.clear() : 모든 요소 삭제

알고리즘

  • 다양한 컨테이너와 독립적으로 동작하는 범용 알고리즘을 제공
  • 반복자덕에 컨테이너의 요소를 추상화하여 일관된 방식으로 접근할 수 있게함
  • find(first, last, 찾을 값) : 컨테이너 내부에서 특정 원소를 찾아 해당 원소의 반복자를 반환하는 함수
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);

// 특정 값 4를 찾음
auto it = find(arr, arr + size, 4);

if (it != arr + size) {
    cout << "값 4가 배열에서 발견됨, 위치: " << (it - arr) << endl;
} else {
    cout << "값 4가 배열에 없음" << endl;
}

...
string str = "hello world";

// 문자열 o찾기
auto it = find(str.begin(), str.end(), 'o');

if (it != str.end()) {
    cout << "문자 'o'가 문자열에서 발견됨, 위치: " << (it - str.begin()) << endl;
} else {
    cout << "문자 'o'가 문자열에 없음" << endl;
}

반복자

  • 컨테이너의 내부 구조는 서로 다르지만, 대부분 알고리즘을 동알한 코드를 활용해서 사용할 수 있었다.
  • 반복자를 기반으로 알고리즘이 동작하기 때문
  • 반복자는 컨테이너의 요소에 대한 일관된 접근 방법을 제공하므로, 알고리즘이 특정 컨테이너의 내부 구현과 무관하게 동작할 수 있습니다.

정방향 반복자

  • begin()은 컨테이너의 첫 번째 원소를 가리키는 반복자, end()는 마지막 원소 다음을 가리키는 반복자
  • end()가 마지막 원소 다음인 이유는 일관된 반복구조를 유지하고, 탐색 실패를 쉽게 표현할 수 있기 때문입니다.

역방향 반복자

  • rbegin()은 컨테이너의 마지막 원소를 가리키는 역방향 반복자
  • rend()는 컨테이너의 첫 번째 원소 이전을 가리키는 역방향 반복자

숙제

객체지향적 설계

객제지향적 코드를 구현하는 능력 배양

  1. 대부분 라이브러리 및 오픈소스는 객체지향적으로 설계되어 있음
  2. 좋은 설계로 구현된 코드는 개발 시간을 단축할 수 있다.
  3. 좋은 설계로 구현된 코드는 기능 변경에 유연하게 대응할 수 있다.

응집도

  • 클래스 또는 모듈 내부의 구성 요소들이 얼마나 밀접하게 관련되어 있는지를 나타냄
  • 응집도가 높을수록 좋은 설계라고 평가
  • 클래스 내부에 관련 없는 기능들이 포함되어 있으면, 변경이 자주 발생하고, 확장하기도 쉽지 않다.

응집도가 낮은 경우

  • 서로 관련없는 기능들이 하나의 클래스에 포함된 경우를 말함

목표가 피자배달인 경우

  1. 피자배달
  2. 웹사이트 디자인
  3. 회사 마케팅
  4. 창고관리

이런 기능들이 한 클래스에 포함되어 있다면 응집도가 낮다고 할 수 있다.

응집도가 높은 경우

  • 서로 관련있는 모듈만 하나의 class에 있는 경우
  1. 피자 배달 경로 확인
  2. 주문한 고객 대응
  3. 배달 예상 시간 측정

결합도

  • 결합도는 모듈 또는 클래스 '간'의 의존성을 말합니다.
  • 일반적으로 결합도는 낮을수록 좋은 코드
  • 결합도가 높으면 하나의 모듈이 변경될때 다른 모듈들에도 영향이 갑니다.

SOLID 원칙

  • 유지보수성 및 확장성 향상
  • 변경에 유연한 설계 제공

단일 책임 원칙(SRP)

  • 각 클래스는 하나의 책임만 가져야 한다.

개방 폐쇄 원칙(OCP)

  • 확장에는 열려있어야하고 수정에는 닫혀있어야 한다.

리스 코프 치환 원칙(LSP)

  • 자식 클래스는 부모 클래스에서 기대되는 행동을 보장해야 한다.
  • 부모 클래스를 사용하는 코드가 자식 클래스로 대체되더라도 정상적으로 동작해야 한다.

인터페이스 분리 원칙(ISP)

  • 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
  • 하나의 거대한 인터페이스보다는 역할별로 세분화된 인터페이스를 만들어 필요한 기능만 구현하도록 설계해야한다.

의존 역전 원칙(DIP)

  • 고수준 모듈은 저 수준 모듈에 직접 의존하는 것이 아니라, 두 모듈 모두 추상화에 의존해야 한다.
  • 인터페이스나 추상 클래스 같은 추상화 계층을 두어 결합도를 낮추는것이 좋은 설계

숙제 1.

숙제 2.

2주차 숙제

1번과제

  • 내 풀이

  • 1번과제 내 풀이인데 아직 도전 기능같은것을 안만들었다.

  • 함수 재사용성, SOLID원칙을 최대한 지키려고했는데 조금 더 고민해봐야 할 것 같다.

0개의 댓글