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

1. WHAT
- thorw: 예외 발생
throw out_of_range("Array index out of range");
out_of_range, overflow_error, length_error, runtime_error
-> throw한 위치에서 즉시 함수 종료, 예외 처리 부분으로 이동
- try - catch: 예외 처리
try {
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[5] = 40; //예외 처리
arr[3] = 50; //실행 X
} catch (const out_of_range& e){
cout << "ERROR: " << e.what() << endl;
}
예외 발생 X -> catch문 무시
예외 발생 O -> stack에 생성된 모든 객체의 소멸자 호출, 가까운 catch문으로 이동 -> 예외에 관한 내용 what()으로 확인
예외를 생성자에서 던질 때 주의해야 할 점
생성자에서 예외가 발생 시에 소멸자가 호출되지 않는다!
만일 예외를 던지기 이전에 획득한 자원이 있다면 catch에서 해제시켜야 한다.
- Range-based for loop: 처음부터 끝까지 순회
for ( 데이터 타입 elem: 데이터 리스트){
elem을 이용한 순회
}
- 객체지향적 설계
- 응집도: 클래스 또는 모듈 내부의 구성 요소들이 얼마나 밀접하게 관련되어 있는지
- 결합도: 모듈 또는 클래스 간의 의존성
- SOLID 원칙
- SRP 단일 책임 원칙: 각 클래스는 하나의 책임만!
- OCP 개방 폐쇄 원칙: 확장에는 열려있고 수정에는 닫혀있어야 함
- LSP 리스 코프 치환 원칙: 자식 클래스는 부모 클래스에서 기대되는 행동 보장
- ISP 인터페이스 분리 원칙: 클라이언트는 자신이 사용하지 않는 메서드에 의존X
- DIP 의존 역전 원칙: 고수준 모듈은 저수준 모듈에 직접 의존X, 두 모듈 모두 추상화에 의존
⁉️ DB 정규화처럼.. 객체지향 설계도 많이 나누면 성능에 문제가 없을까에 대한 궁금증
✅ 클래스를 쪼개야 할 때
- 변경 이유가 다를 때
- 재사용 가능성이 명확할 때
- 정책/규칙/행위가 포함될 때
- 테스트 단위로 분리할 수 있을 때
❌ 쪼개지 말아야 할 때
- 단순 데이터 묶음일 뿐일 때
- 항상 함께 생성·삭제·변경될 때
- 의미 없는 위임만 생길 때
- 클래스 이름이 설명하기 어려울 때
DB 정규화는 데이터 무결성을 위해 구조를 쪼개고, 객체지향 설계는 변경 이유를 기준으로 책임을 쪼갠다.
둘 다 과하면 오히려 성능과 생산성을 해친다.
2. RESULT
- 도전 실습 2-1
#include <iostream>
#include <memory>
using namespace std;
class Data
{
public:
int value;
Data(int v) : value(v)
{
cout << "[INFO] Data(" << value << ") 객체 생성됨.\n";
}
~Data()
{
cout << "[INFO] Data(" << value << ") 객체 소멸됨.\n";
}
};
void RepresentDanglingPointer()
{
std::cout << "\n === 메모리 테스트 ===\n";
// 1. 힙에 Data 객체를 할당하고, 두 개의 Raw Pointer에 주소를 저장하세요.
Data* raw_ptr1 = new Data(43);
Data * raw_ptr2 = raw_ptr1;
cout << "Raw Ptrs 값: " << raw_ptr1->value << "\n";
// 2. raw_ptr1을 사용하여 메모리를 해제합니다.
delete raw_ptr1;
cout << "raw_ptr1로 메모리 해제 완료.\n";
// 3. raw_ptr2를 이용하여 메모리를 해제합니다.
// 런타임 에러(Crash)를 유발할 수 있습니다.
cout << "raw_ptr2로 해제 시도...\n";
delete raw_ptr2;
}
void SharedPointer()
{
std::cout << "\n === 메모리 테스트 ===\n";
// 1. 힙에 Data 객체를 할당하고, 두 개의 Pointer에 주소를 저장하세요.
shared_ptr<Data>ptr1 = make_shared<Data>(43);
shared_ptr<Data>ptr2 = ptr1;
cout << "Ptrs 값: " << ptr1->value << "\n";
// 2. ptr1 소유권을 해제 (참조 카운트 감소)
ptr1.reset();
cout << "ptr1로 메모리 해제 완료.\n";
// 3. ptr2 소유권을 해제 (참조 카운트 감소)
cout << "ptr2로 해제 시도...\n";
ptr2.reset();
}
int main() {
SharedPointer();
return 0;
}
- 도전 실습 2-2
// 인덱스 연산자 []를 오버로딩하여 구현 - 읽기/쓰기
#include <iostream>
using namespace std;
template <typename T>
class Array {
T data[100];
int size;
public:
Array() : size(0) {}
T& operator[](int index) {
if (index<0|| size < index) {
throw out_of_range("Array index out of range");
}
if (index==size)
size++;
return data[index];
}
void add(const T& element) {
if (size < 100)
data[size++] = element;
}
void remove() {
if (size > 0)
size--;
}
void print() {
for (int i = 0; i < size; i++)
cout << data[i] << " ";
cout << endl;
}
};
int main() {
Array<int> arr; // 정수형 배열 생성
try {
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[5] = 40; //예외 처리
arr[3] = 50; //실행 X
}
catch (const out_of_range& e){
cout << "ERROR: " << e.what() << endl;
}
arr.print();
cout << arr[0] << endl;
return 0;
}
읽기와 쓰기에 대해서도 구분하고 싶었는데... 그럼 연산자 오버로딩을 더 깊에 들어가야해서 너무 어렵다..ㅠㅠㅠㅠㅠ
연산자 오버로딩 더 공부해야겠다...
- 도전X도전 실습 2-2
// 제공되는 코드에 foreach를 동작시키기 위해 필요한 함수를 추가
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class Array {
T data[100];
int size;
public:
Array() : size(0) {}
void add(const T& element) {
if (size < 100)
data[size++] = element;
}
void remove() {
if (size > 0)
size--;
}
void print() {
vector <T> temp(data, data + size);
for (T item : temp) { // Range-based for loop
cout << item << " ";
}
cout << endl;
}
};
int main() {
Array<int> arr; // 정수형 배열 생성
arr.add(10);
arr.add(20);
arr.add(30);
arr.print();
arr.remove();
arr.print();
return 0;
}
// 출력결과:
// 10 20 30
// 10 20
제대로 한게 맞나....? --> 튜터님 찾아감

- 2주차 숙제

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
struct Movie {
string title;
double rating;
};
// TODO: MovieProcessor 추상 클래스 정의
// 순수 가상 함수 process를 선언해야 합니다.
// process는 vector<Movie>&를 인자로 받아야 합니다.
class MovieProcessor {
public:
virtual void process(vector<Movie>& movies) = 0;
virtual ~MovieProcessor() {} //소멸자 까먹음 !!!!
};
// 기본 영화 관리자
class MovieManager {
private:
vector<Movie> movies;
map<string, double> movieMap;
public:
MovieManager() {
// 초기 데이터 설정
movies = {
{"Inception", 9.0},
{"Interstellar", 8.6},
{"The Dark Knight", 9.1},
{"Memento", 8.4}
};
for (const auto& movie : movies) {
movieMap[movie.title] = movie.rating;
}
}
void printMovies() {
cout << "영화 목록:\n";
for (const auto& movie : movies) {
cout << "제목: " << movie.title << ", 평점: " << movie.rating << "\n";
}
}
void findMovie(const string& title) {
auto it = movieMap.find(title);
if (it != movieMap.end()) {
cout << "영화 제목: " << it->first << ", 평점: " << it->second << "\n";
}
else {
cout << "해당 영화는 목록에 없습니다.\n";
}
}
// MovieProcessor를 사용하여 기능 확장
void processMovies(MovieProcessor& processor) {
processor.process(movies);
}
};
// TODO: compareMovies 함수 정의
// Movies 객체의 대소를 비교하는 함수 입니다.
// STL에서 제공하는 sort 함수를 활용해서 vector<Movie>를 멤버변수 rating 기준 내림차순으로 정렬 할 수 있도록 해야 합니다.
bool compareMovies(const Movie& a, const Movie& b) {
return a.rating > b.rating;
}
// TODO: RatingSorter 클래스 정의
// MovieProcessor를 상속받아 구현합니다.
// process 는 vector<Movie>&를 인자로 받으며 영화목록이 저장되어 있습니다.
// process는 인자로 받은 벡터는 내림차순으로 정렬하고, 정렬된 영화목록을 출력합니다.
class RatingSorter : public MovieProcessor {
public:
void process(vector<Movie>& movies) {
sort(movies.begin(), movies.end(), compareMovies);
cout << "평점 기준 정렬된 영화 목록:" << endl;
for (const auto& movie : movies) {
cout << "제목: " << movie.title << ", 평점: " << movie.rating << endl;
}
}
};
// 구체 클래스: 특정 평점 이상의 영화 필터링
class RatingFilter : public MovieProcessor {
private:
double minRating;
public:
explicit RatingFilter(double minRating) : minRating(minRating) {}
void process(vector<Movie>& movies) {
cout << "평점 " << minRating << " 이상인 영화 목록:\n";
for (const auto& movie : movies) {
if (movie.rating >= minRating) {
cout << "제목: " << movie.title << ", 평점: " << movie.rating << "\n";
}
}
}
};
int main() {
MovieManager manager;
cout << "1. 영화 목록 출력\n";
manager.printMovies();
cout << "\n2. 영화 검색 (예: Interstellar)\n";
manager.findMovie("Interstellar");
cout << "\n3. 평점 기준 정렬 및 출력\n";
RatingSorter sorter;
manager.processMovies(sorter);
cout << "\n4. 평점 8.5 이상인 영화 필터링 및 출력\n";
RatingFilter filter(8.5);
manager.processMovies(filter);
return 0;
}
3. FIX
- 도전X도전 실습 수정
// 제공되는 코드에 foreach를 동작시키기 위해 필요한 함수를 추가
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class Array {
T data[100];
int size;
public:
Array() : size(0) {}
void add(const T& element) {
if (size < 100)
data[size++] = element;
}
void remove() {
if (size > 0)
size--;
}
void print() {
vector <T> temp(data, data + size);
for (T item : temp) { // Range-based for loop
cout << item << " ";
}
cout << endl;
}
// 시작 위치 (첫 번째 원소의 주소)
T* begin() { return &data[0]; }
// 끝 위치 (마지막 원소 다음의 주소)
T* end() { return &data[size]; }
};
int main() {
Array<int> arr; // 정수형 배열 생성
arr.add(10);
arr.add(20);
arr.add(30);
arr.print();
arr.remove();
arr.print();
for (auto n : arr) { // Range-based for loop
cout<<n << endl;
}
return 0;
}
begin()과 end()만 있으면 컨테이너가 아니어도 range-based for 사용 가능!
range-based for 문은 내부적으로 begin()과 end()를 호출하여 시작과 끝 반복자를 얻고, 반복자를 증가시키며 순회.
포인터는 반복자 연산을 지원하므로 배열의 주소를 반환하면 사용자 정의 클래스도 range-based for를 사용할 수 있다.
4. 참고
[C++] 오버로딩 (Overloading) - 2. 연산자
[C++] 오버로딩 (Overloading) - 1.함수, 생성자 오버로딩 (overloading) 같은 이름의 메소드(method) 또는 생성자를 매개변수의 개수나 타입을 다르게 지정함으로써 2개 이상 정의하는 것 함수 오버로딩 함
wn42.tistory.com
씹어먹는 C ++ - <11. C++ 에서 예외 처리>
모두의 코드 씹어먹는 C ++ - <11. C++ 에서 예외 처리> 작성일 : 2018-09-17 이 글은 90244 번 읽혔습니다. 안녕하세요 여러분! 오래 간만에 인사 드립니다. 이번 강좌에서는 C++ 에서 예외 처리를 어떠한
modoocode.com
https://blockdmask.tistory.com/319
[C++] range based for, 범위기반 for 반복문에 대해서.
안녕하십니까. BlockDMask입니다.오늘 공부할 내용은 C++11에 추가된 범위기반 반복문 range based for문 입니다. 혁명이죠. 놀랍죠. 하지만 범위기반 for문이 완전히 for문을 대체하지 못합니다. why? 왜때
blockdmask.tistory.com
https://www.youtube.com/watch?v=YnhNgMJvQh0&t=2s
C++ Insights
C++ Insights - See your source code with the eyes of a compiler.
cppinsights.io
https://en.cppreference.com/w/cpp/language/range-for.html
Range-based for loop (since C++11) - cppreference.com
Executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container. [edit] Syntax attr (optional) for ( init-statement (optional) item-declaration
en.cppreference.com
'내배캠Unreal_TIL > C++' 카테고리의 다른 글
| [C++] STL 총정리 (0) | 2025.12.18 |
|---|---|
| [TIL] 2025-12-18 | 과제3 구현 및 vector 동작 원리 이해 (0) | 2025.12.18 |
| [TIL] 2025-12-16 | C++ STL, vector, map, sort(), find(), Iterator (2) | 2025.12.16 |
| [TIL] 2025-12-15 | C++ 스마트 포인터, 템플릿 (0) | 2025.12.15 |
| [TIL] 2025-12-12 | 과제1 구현 및 입력 실패 처리, C++ 힙메모리 (0) | 2025.12.12 |