2025. 2. 22. 18:54ㆍ프로그래밍 언어/C++
1. C++ 소개 및 개발 환경 설정
1.1 C++ 개요 및 특징
- C++의 탄생과 역사
- C++의 개발 배경 (Bjarne Stroustrup, 1983년 발표)
- C와의 차이점 (객체지향 프로그래밍 지원)
- 실무에서의 활용 (게임 개발, 임베디드 시스템, 금융 시스템 등)
- C++의 주요 특징
- 객체지향 프로그래밍 (OOP: 캡슐화, 상속, 다형성)
- 메모리 관리 (동적 메모리 할당, 스마트 포인터)
- 표준 라이브러리 (STL: vector, map, set 등)
- 성능과 최적화 (컴파일 언어, 최적화 가능성)
- C와의 호환성 (C 언어 코드 실행 가능)
- 최신 기능 (템플릿, 람다, 모듈 등)
1.2 C++ 표준 버전 개요
- C++ 표준 버전별 주요 변화
- C++98 (최초 표준화, 기본적인 OOP 기능)
- C++03 (C++98 보완)
- C++11 (스마트 포인터, auto, 람다 함수, nullptr 도입)
- C++14 (일부 C++11 개선, std::make_unique)
- C++17 (std::optional, if constexpr, 구조적 바인딩)
- C++20 (concepts, ranges, coroutines)
- C++23 (std::expected, 개선된 모듈 시스템)
1.3 개발 환경 설정
- C++ 개발 도구 선택
- 다양한 컴파일러와 IDE 비교
- GCC, Clang, MSVC 등의 차이점
- 컴파일러 및 IDE 설치
- Windows
- MinGW-w64 설치 방법 (GCC 사용)
- Visual Studio Community 설치 (MSVC 사용)
- WSL을 활용한 Ubuntu + Clang 환경 설정
- MacOS
- Homebrew를 사용한 Clang/GCC 설치
- Xcode 및 터미널에서 C++ 컴파일 환경 설정
- Linux (Ubuntu, Debian)
- sudo apt install g++로 설치 및 확인
- Windows
- IDE 및 텍스트 에디터 설정
- Visual Studio Code
- 확장 기능(C++ IntelliSense, CMake, Debugging)
- tasks.json을 활용한 빌드 시스템 설정
- CLion (JetBrains)
- CMake 프로젝트 설정
- Visual Studio
- MSVC 기반 프로젝트 생성 방법
- 터미널 사용
- GCC, Clang을 활용한 명령줄 컴파일 (g++ main.cpp -o main)
- make 및 CMake 소개
- Visual Studio Code
1.4 첫 번째 C++ 프로그램 실행
- Hello, World! 프로그램 작성
- #include <iostream>
- int main()
- {
- std::cout << "Hello, World!" << std::endl;
- return 0;
- }
- 코드 설명
- #include <iostream>: 표준 입출력 라이브러리 포함
- int main(): C++ 프로그램의 진입점
- std::cout: 콘솔 출력
- std::endl: 줄바꿈
- return 0;: 정상 종료 의미
- 컴파일 및 실행 방법
- GCC 사용: g++ main.cpp -o main && ./main
- MSVC 사용: cl main.cpp && main.exe
- Visual Studio Code에서 실행하는 방법
- 디버깅 기본 설정 (gdb / lldb 소개)
2. 기본 문법
2.1 변수와 데이터 타입
C++에서 변수를 선언하고 사용할 때, 데이터 타입을 지정해야 한다.
(1) 기본 데이터 타입
데이터 타입 | 크기 (보통) | 설명 |
int | 4바이트 | 정수형 (예: 42, -10) |
float | 4바이트 | 단정도 부동소수점 (예: 3.14f) |
double | 8바이트 | 배정도 부동소수점 (예: 3.1415926535) |
char | 1바이트 | 단일 문자 (예: 'A', 'b') |
bool | 1바이트 | 참/거짓 (true, false) |
int age = 25;
float pi = 3.14f;
double precisePi = 3.1415926535;
char grade = 'A';
bool isPassed = true;
(2) 변수 선언 및 초기화
- int x; → 선언만 함 (초기화되지 않음)
- int y = 10; → 선언과 동시에 초기화
2.2 auto 타입 추론 (C++11)
C++11부터 auto 키워드를 사용하면 변수 타입을 컴파일러가 자동으로 추론할 수 있다.
auto num = 42; // int
auto pi = 3.14; // double
auto isValid = true; // bool
- 코드의 가독성을 높이고, 타입을 명확하게 알 필요가 없을 때 유용하다.
2.3 기본 입출력 (cin, cout)
(1) 표준 출력 (std::cout)
#include <iostream>
int main() {
std::cout << "Hello, C++!" << std::endl;
return 0;
}
- std::cout → 콘솔에 출력
- std::endl → 줄바꿈
(2) 표준 입력 (std::cin)
#include <iostream>
int main() {
int age;
std::cout << "나이를 입력하세요: ";
std::cin >> age;
std::cout << "입력한 나이: " << age << std::endl;
return 0;
}
- std::cin >> 변수명; → 입력을 받음
- >> 연산자로 여러 개의 입력 가능 (std::cin >> a >> b;)
2.4 주석 (//, /* */)
C++에서는 코드에 설명을 추가할 때 주석(comment)을 사용한다.
(1) 한 줄 주석 (//)
// 이 줄은 주석 처리됨
std::cout << "Hello, C++!" << std::endl; // 이 부분도 주석
(2) 여러 줄 주석 (/* */)
/*
여러 줄의 주석을 사용할 때
이 방법을 사용한다.
*/
std::cout << "주석 예제" << std::endl;
- 코드 실행에 영향을 미치지 않으며, 설명을 추가할 때 유용하다.
2.5 연산자 (+, -, *, /, %, ++, --)
(1) 산술 연산자
연산자 | 설명 | 예제 |
+ | 덧셈 | a + b |
- | 뺄셈 | a - b |
* | 곱셈 | a * b |
/ | 나눗셈 | a / b (정수 나눗셈은 몫만 반환) |
% | 나머지 연산 | a % b (정수만 가능) |
int a = 10, b = 3;
std::cout << a / b; // 출력: 3 (정수 나눗셈)
std::cout << a % b; // 출력: 1 (나머지)
(2) 증가 및 감소 연산자 (++, --)
연산자 | 설명 | 예제 |
++a | 전위 증가 | 먼저 증가 후 연산 수행 |
a++ | 후위 증가 | 연산 수행 후 증가 |
--a | 전위 감소 | 먼저 감소 후 연산 수행 |
a-- | 후위 감소 | 연산 수행 후 감소 |
int x = 5;
std::cout << ++x; // 6 (먼저 증가)
std::cout << x++; // 6 (출력 후 증가, x는 7이 됨)
std::cout << --x; // 6 (먼저 감소)
2.6 형 변환 (static_cast, 묵시적 & 명시적 변환)
(1) 묵시적 변환 (Implicit Conversion)
- 작은 타입 → 큰 타입으로 자동 변환
int num = 10;
double d = num; // int → double 자동 변환
std::cout << d; // 출력: 10.0
- char → int → float → double 순서로 자동 변환됨
(2) 명시적 변환 (Explicit Conversion)
- static_cast<T>(변수명)을 사용하여 명시적으로 변환
double pi = 3.14159;
int intPi = static_cast<int>(pi); // 소수점 제거
std::cout << intPi; // 출력: 3
- C 스타일 변환 ((int)pi)보다 안전하고 명확한 변환 방식이다.
주제 | 설명 |
2.1 변수와 데이터 타입 | int, float, double, char, bool 기본 타입 소개 |
2.2 auto 타입 추론 (C++11) | 컴파일러가 타입을 자동으로 추론하는 기능 |
2.3 기본 입출력 (cin, cout) | 표준 입출력 스트림 개념과 활용 |
2.4 주석 (//, /* */) | 코드 내 설명을 위한 주석 사용법 |
2.5 연산자 (+, -, *, /, %, ++, --) | 산술 연산 및 증가/감소 연산자 활용 |
2.6 형 변환 | 묵시적 변환과 명시적 변환 (static_cast) |
3. 제어문 (Control Statements)
제어문은 프로그램의 흐름을 조정하는 역할을 하며, 조건에 따라 실행 경로를 변경하거나 특정 코드를 반복적으로 실행하는 데 사용된다.
번호 | 주제 | 설명 |
3.1 조건문 | if-else, switch-case | 조건을 검사하여 코드 실행 흐름을 변경 |
3.2 반복문 | for, while, do-while | 특정 조건이 만족될 때까지 반복 실행 |
3.3 if constexpr (C++17) | 컴파일 시간 조건문 | if 문을 컴파일 타임에서 실행 |
📌 3.1 조건문 (Conditional Statements)
조건문은 주어진 조건을 평가하여 코드 실행을 결정하는 역할을 한다.
(1) if-else 문
- 조건이 true이면 실행, false이면 실행하지 않음
- else if를 사용하여 여러 개의 조건을 검사 가능
(2) switch-case 문
- 여러 개의 값을 비교할 때 사용
- break를 사용하여 각 case 종료
- default를 사용하여 기본 동작 지정
📌 3.2 반복문 (Loops)
반복문은 특정 조건이 만족될 때까지 코드 블록을 실행하는 구조이다.
(1) for 문
- 고정된 횟수만큼 반복할 때 사용
- 초기화 → 조건 검사 → 실행 → 증감 순서로 동작
(2) while 문
- 조건이 true인 동안 계속 실행
- 반복 횟수가 정해지지 않은 경우 사용
(3) do-while 문
- 최소 한 번 실행한 후, 조건이 true이면 반복 실행
- 사용자 입력 기반 프로그램 등에 활용됨
📌 3.3 if constexpr (C++17, Compile-Time If Statement)
- 컴파일 타임에서 조건을 평가하여 불필요한 코드를 제거하는 최적화 기법
- 템플릿 프로그래밍에서 유용하게 사용됨
- 일반 if 문과 달리 실행 시 조건 평가가 아니라 컴파일 시 결정됨
📌 4. 함수와 변수의 범위 (Functions and Variable Scope)
C++에서 함수(Function)는 특정 작업을 수행하는 코드 블록이며, 변수의 범위(Variable Scope)는 변수가 접근 가능한 영역을 의미한다.
이 단원에서는 C++에서 함수와 변수의 범위를 다루며, 함수의 다양한 특성과 효율적인 코드 작성 방법을 설명한다.
📌 4.1 함수 선언과 정의 (Function Declaration & Definition)
함수를 사용하려면 먼저 선언(Declaration)과 정의(Definition)을 알아야 한다.
🔹 함수 선언과 정의
- 함수 선언: 함수의 이름, 반환 타입, 매개변수를 지정하지만, 본문(Body)은 없음.
- 함수 정의: 함수의 실제 실행 내용을 포함한 코드 블록.
📌 세부 내용
- 함수 선언과 정의의 차이
- 반환 값(Return)과 매개변수(Arguments)
- 값 전달(Call by Value) vs 참조 전달(Call by Reference)
- 함수 프로토타입(Function Prototype) 사용법
📌 4.2 함수 오버로딩 (Function Overloading)
같은 이름을 가진 여러 개의 함수를 정의할 수 있는 기능.
매개변수의 타입(type) 또는 개수(number)가 다르면 다른 함수로 간주됨.
📌 세부 내용
- 함수 오버로딩의 기본 원칙
- 매개변수 개수와 타입을 이용한 차별화
- 오버로딩의 활용 예제
📌 4.3 기본 매개변수 (Default Arguments)
함수의 매개변수에 기본값을 설정하여, 호출 시 값을 생략하면 기본값이 자동으로 적용된다.
📌 세부 내용
- 기본 매개변수의 정의 및 사용법
- 기본값이 설정된 매개변수의 우선순위
- 오버로딩과 기본 매개변수의 차이점
- C++ 표준 라이브러리에서의 활용 예시
📌 4.4 변수의 범위 (Variable Scope)
변수는 선언된 위치에 따라 접근 가능 범위(Scope)가 결정된다.
🔹 변수의 종류
- 전역 변수 (Global Variables)
- 프로그램 전체에서 접근 가능.
- 지역 변수 (Local Variables)
- 특정 함수 또는 코드 블록 내에서만 사용 가능.
- 정적 변수 (static Variables)
- 한 번만 초기화되고, 함수 호출이 끝나도 값이 유지됨.
- 상수 (const Variables)
- 변경할 수 없는 변수.
📌 세부 내용
- 전역 변수 vs 지역 변수
- static 변수의 동작 원리
- const 변수와 constexpr 변수의 차이
- 메모리 관리와 성능 최적화 관련 고려사항
📌 4.5 inline 함수 (Inline Functions)
함수를 호출할 때 발생하는 오버헤드를 줄이기 위해, 컴파일러가 함수 호출을 코드로 직접 치환하는 기능.
📌 세부 내용
- inline 함수의 개념
- 컴파일러의 inline 최적화 방식
- inline 함수의 장점과 단점
- 짧은 함수에서 inline을 사용해야 하는 이유
- C++17 이후 constexpr과의 관계
번호 | 주제 | 설명 |
4.1 함수 선언과 정의 | 함수의 기본 구조 | 선언 vs 정의, 매개변수 전달 방식 |
4.2 함수 오버로딩 | 같은 이름의 함수 여러 개 정의 | 매개변수의 개수와 타입을 이용한 차별화 |
4.3 기본 매개변수 | 매개변수 기본값 설정 | 함수 호출 시 생략 가능 |
4.4 변수의 범위 | 전역, 지역, 정적, 상수 변수 | 변수의 생명 주기와 메모리 관리 |
4.5 inline 함수 | 실행 속도 최적화 | 함수 호출 오버헤드 감소 |
📌 5. 포인터와 참조 (Pointers and References)
C++에서 포인터(Pointer)와 참조(Reference)는 메모리 주소를 직접 다루는 기능을 제공한다.
포인터와 참조를 사용하면 효율적인 메모리 관리와 객체 제어가 가능하지만, 올바르게 사용하지 않으면 메모리 누수(Memory Leak)나 프로그램 오류가 발생할 수 있다.
C++11에서는 스마트 포인터(Smart Pointer)가 도입되어 메모리 관리를 자동화할 수 있다.
이 단원에서는 포인터와 참조를 다루며, 동적 메모리 할당 및 스마트 포인터의 활용까지 학습한다.
📌 5.1 포인터 기본 개념 (*, &, nullptr)
포인터는 메모리 주소를 저장하는 변수이며, 이를 통해 동적 메모리 할당과 배열, 객체의 직접 제어가 가능하다.
🔹 포인터 연산자
연산자 | 설명 |
* | 포인터 변수를 선언하거나, 포인터가 가리키는 값을 참조할 때 사용 |
& | 변수의 주소를 가져올 때 사용 |
nullptr | 포인터가 아무것도 가리키지 않음을 나타내는 값 (C++11 이상) |
📌 세부 내용
- 포인터 변수 선언 및 초기화
- nullptr을 사용한 안전한 포인터 초기화
- 포인터를 활용한 배열 및 문자열 처리
📌 5.2 동적 메모리 할당 (new, delete)
C++에서는 new와 delete 키워드를 사용하여 런타임에 동적으로 메모리를 할당 및 해제할 수 있다.
동적 메모리 할당을 적절히 사용하면 프로그램 실행 중 필요한 만큼의 메모리를 할당할 수 있지만, 메모리 누수를 방지하기 위해 반드시 delete를 사용하여 해제해야 한다.
📌 세부 내용
- new와 delete를 사용한 동적 메모리 할당 및 해제
- 배열의 동적 할당 (new[], delete[])
- 메모리 누수 방지 및 올바른 해제 방법
📌 5.3 참조 (& 연산자)
참조(Reference)는 포인터와 유사하지만, 한 번 초기화되면 다른 변수를 가리킬 수 없는 특징이 있다.
참조는 함수의 매개변수를 전달할 때, 복사 오버헤드를 줄이기 위해 자주 사용된다.
📌 세부 내용
- 참조 변수의 선언 및 초기화
- 포인터와 참조의 차이점
- 함수 매개변수에서 참조의 활용 (Call by Reference)
📌 5.4 스마트 포인터 (std::unique_ptr, std::shared_ptr)
C++11부터 스마트 포인터(Smart Pointer)가 도입되어, 개발자가 직접 delete를 호출하지 않아도 자동으로 메모리가 관리된다.
스마트 포인터를 사용하면 메모리 누수를 방지하고, 안전한 동적 객체 관리가 가능하다.
📌 세부 내용
- std::unique_ptr (단독 소유권을 가지는 스마트 포인터)
- std::shared_ptr (참조 카운트를 사용하는 공유 스마트 포인터)
- std::weak_ptr (순환 참조 문제 해결)
번호 | 주제 | 설명 |
5.1 포인터 기본 개념 | 포인터의 선언 및 사용법 | *, &, nullptr의 의미 및 활용 |
5.2 동적 메모리 할당 | new, delete를 통한 메모리 관리 | 메모리 누수 방지 및 동적 배열 처리 |
5.3 참조 (&) | 참조 변수 및 함수 매개변수 전달 방식 | 포인터와 참조의 차이점 및 장점 |
5.4 스마트 포인터 | std::unique_ptr, std::shared_ptr | 스마트 포인터를 통한 메모리 자동 관리 |
📌 6. 배열과 문자열
C++에서 배열(Array)과 문자열(String)은 데이터를 효율적으로 저장하고 처리하는 중요한 자료구조이다.
기본적인 배열과 다차원 배열, C-스타일 문자열, C++ 표준 라이브러리의 std::vector 및 std::string을 학습한다.
📌 6.1 배열 (int arr[5];)
배열은 같은 데이터 타입을 연속된 메모리 공간에 저장하는 자료구조이다.
- 배열 선언 및 초기화
- 배열의 요소 접근 및 수정
- 배열 크기 및 반복문을 이용한 순회
- 배열과 포인터의 관계
📌 6.2 다차원 배열 (int matrix[3][3];)
다차원 배열은 2차원 이상의 데이터를 저장할 수 있는 배열이다.
- 2차원 배열 선언 및 초기화
- 다차원 배열 요소 접근 및 수정
- 중첩 반복문을 이용한 다차원 배열 순회
- 배열의 동적 할당을 이용한 다차원 배열 활용
📌 6.3 std::vector (C++98부터 사용 가능)
std::vector는 배열의 단점을 보완한 동적 크기 조절이 가능한 컨테이너이다.
- std::vector 선언 및 초기화
- push_back, size, at 등의 기본적인 기능
- 반복문을 이용한 std::vector 순회
- 동적 크기 조절과 메모리 관리의 차이점
📌 6.4 C-스타일 문자열 (char str[])
C-스타일 문자열은 char 배열을 사용하여 문자열을 표현하는 방식이다.
- C-스타일 문자열 선언 및 초기화
- 문자열 입력 및 출력 (cin, cout, gets 등)
- strlen, strcpy, strcmp 등의 문자열 처리 함수
- C-스타일 문자열과 std::string의 차이점
📌 6.5 std::string (C++ 표준 문자열)
C++의 std::string 클래스는 문자열을 안전하고 편리하게 다룰 수 있도록 제공되는 표준 라이브러리이다.
- std::string 선언 및 초기화
- 문자열 입력 (std::getline)
- 문자열 길이 (length)
- 문자열 추가 (append, +=)
- 문자열 비교 (==, !=, compare)
- 부분 문자열 (substr) 및 검색 (find)
번호 | 주제 | 설명 |
6.1 배열 | 기본 배열 선언 및 사용 | 정적 배열, 요소 접근, 크기 및 반복문 활용 |
6.2 다차원 배열 | 2차원 배열 및 다차원 배열 | 행렬 형태의 데이터 저장 및 활용 |
6.3 std::vector | 동적 배열 컨테이너 | push_back, size, 동적 크기 조절 |
6.4 C-스타일 문자열 | char 배열 기반 문자열 | strlen, strcpy, strcmp 등 활용 |
6.5 std::string | 표준 라이브러리 문자열 | getline, length, append 등 편리한 문자열 조작 |
📌 7. 구조체와 클래스
C++에서 구조체(struct)와 클래스(class)는 사용자 정의 데이터 타입을 만들기 위한 기능이다.
구조체는 단순한 데이터 묶음 역할을 하며, 클래스는 객체 지향 프로그래밍(OOP)을 지원한다.
이 장에서는 구조체와 클래스의 차이, 생성자와 소멸자, 접근 지정자, this 포인터, const 멤버 함수 등을 학습한다.
📌 7.1 구조체 (struct)
구조체(struct)는 여러 개의 데이터를 하나로 묶을 수 있는 사용자 정의 자료형이다.
C++에서는 구조체도 멤버 함수 포함 가능하나, 일반적으로 데이터 저장 용도로 사용된다.
- 구조체 선언 및 초기화
- 구조체 멤버 변수와 함수
- 구조체를 함수의 매개변수로 전달하는 방법 (값 전달 vs 참조 전달)
📌 7.2 클래스 (class vs struct)
C++에서는 struct와 class 모두 데이터와 함수를 포함할 수 있지만, 기본 접근 지정자가 다름.
- struct와 class의 차이점
- 객체 선언 및 초기화
- 클래스를 사용한 캡슐화 및 데이터 보호
- 객체 배열 및 포인터 활용
📌 7.3 생성자와 소멸자 (Constructor & Destructor)
클래스에는 객체가 생성될 때 자동으로 호출되는 생성자(Constructor)와 객체가 소멸될 때 호출되는 소멸자(Destructor)가 존재한다.
- 생성자 개념 및 역할
- 매개변수를 받는 생성자 (오버로딩)
- 소멸자의 역할과 자동 호출
- 동적 메모리 할당과 소멸자 활용 (new/delete)
📌 7.4 접근 지정자 (private, public, protected)
클래스 멤버의 접근을 제어하는 접근 지정자(Access Specifier)에 대해 학습한다.
- private, public, protected의 차이점
- 정보 은닉(Encapsulation)과 데이터 보호
- 클래스 내부 vs 외부에서의 접근 제한
- 상속과 접근 지정자 (protected의 역할 포함)
📌 7.5 this 포인터
클래스 내부에서는 객체 자신을 가리키는 this 포인터가 존재한다.
- this 포인터 개념 및 활용
- 멤버 함수에서 this를 활용하는 방법
- 메서드 체이닝(Method Chaining)
📌 7.6 const 멤버 함수
객체의 데이터를 변경하지 않도록 보장하는 const 멤버 함수를 사용하면, 코드의 안정성을 높이고 예측 가능한 설계를 할 수 있다.
- const 멤버 함수 선언 및 활용
- 객체 내부 데이터를 변경하지 않는 함수 작성
- const 객체에서 const 멤버 함수만 호출 가능
- 클래스 내 mutable 키워드 활용
번호 | 주제 | 설명 |
7.1 구조체 (struct) | 사용자 정의 자료형 | 멤버 변수, 멤버 함수 포함 가능 |
7.2 클래스 (class) | 객체 지향 프로그래밍 | struct와 차이점, 객체 선언 및 활용 |
7.3 생성자 & 소멸자 | 객체의 초기화 및 정리 | 생성자의 오버로딩, 소멸자의 자동 호출 |
7.4 접근 지정자 | private, public, protected | 정보 은닉 및 상속에서의 접근 |
7.5 this 포인터 | 객체 자기 참조 | 메서드 체이닝 및 멤버 함수에서 활용 |
7.6 const 멤버 함수 | 데이터 보호 및 안전한 코드 작성 | const 함수 선언, mutable 키워드 활용 |
📌 8. 객체지향 프로그래밍 (OOP)
C++은 객체지향 프로그래밍(Object-Oriented Programming, OOP) 언어이며, 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)을 기본 개념으로 한다.
또한 가상 함수(Virtual Function), 인터페이스(Interface), C++11의 새로운 기능(override, final, explicit) 등을 포함하여 OOP의 핵심 개념을 학습한다.
📌 8.1 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)
객체지향 프로그래밍(OOP)의 3대 핵심 개념
- 캡슐화 → 데이터 보호 및 정보 은닉 (private, public, protected 활용).
- 상속 → 기존 클래스의 기능을 확장하여 새로운 클래스를 생성 (class Derived : public Base 형태).
- 다형성 → 동일한 함수 이름을 사용하지만, 객체에 따라 다른 동작 수행 (virtual 함수, 함수 오버로딩, 오버라이딩).
📌 세부 내용
- 캡슐화(Encapsulation)
- 정보 은닉(데이터 보호) 및 접근 지정자(private, public, protected).
- getter, setter를 활용한 데이터 접근 방식.
- 상속(Inheritance)
- 기본 상속 구조 및 사용법 (public, protected, private 상속).
- 부모 클래스(기본 클래스)와 자식 클래스(파생 클래스) 개념.
- 다형성(Polymorphism)
- 함수 오버로딩(Overloading)과 함수 오버라이딩(Overriding).
- 가상 함수(Virtual Function)와 동적 바인딩(Dynamic Binding).
📌 8.2 virtual 함수와 오버라이딩 (Overriding)
C++의 virtual 함수를 사용하면 기본 클래스에서 선언한 함수를 파생 클래스에서 재정의(Overriding)할 수 있음.
이를 통해 객체의 동적 바인딩(Dynamic Binding)과 다형성을 구현 가능.
📌 세부 내용
- 가상 함수(virtual function)의 개념과 필요성
- 정적 바인딩(Static Binding) vs. 동적 바인딩(Dynamic Binding).
- virtual 키워드를 사용하여 가상 함수 선언.
- 오버라이딩(Overriding)의 구현 방법
- virtual 함수의 동작 방식과 예제.
- 기본 클래스와 파생 클래스에서 같은 함수명이 있을 때의 동작 방식.
- 포인터와 참조를 이용한 다형성 구현
- 기본 클래스 포인터(Base* ptr = new Derived;)를 사용한 함수 호출.
- 가상 소멸자(virtual ~Base())의 필요성.
📌 8.3 순수 가상 함수 (= 0)
순수 가상 함수(Pure Virtual Function)를 사용하면 추상 클래스(Abstract Class)를 만들 수 있음.
이를 통해 인터페이스(Interface) 역할을 하는 클래스를 정의하고, 자식 클래스에서 반드시 특정 함수를 구현하도록 강제할 수 있다.
📌 세부 내용
- 순수 가상 함수란? (virtual 함수명() = 0;)
- 순수 가상 함수를 포함하는 클래스는 추상 클래스가 됨.
- 추상 클래스(Abstract Class)의 역할
- 인스턴스 생성이 불가능하고, 상속을 통해 기능을 확장하도록 강제함.
- 순수 가상 함수의 구현 방식
- 파생 클래스에서 override하여 반드시 구현해야 함.
- 가상 함수 테이블(Virtual Table, V-Table)과 다형성 원리.
📌 8.4 인터페이스 개념 (Interface)
C++에는 Java나 C#과 같은 interface 키워드는 없지만, 추상 클래스(Abstract Class)를 활용하여 인터페이스를 구현 가능.
📌 세부 내용
- 인터페이스의 정의
- 추상 클래스를 통해 인터페이스를 구현하는 방법.
- virtual 함수만 포함하는 클래스는 순수 인터페이스(Pure Interface)로 사용 가능.
- 다중 상속을 활용한 인터페이스 구현
- class Derived : public Interface1, public Interface2 형태로 다중 상속 가능.
- C++에서 인터페이스를 사용할 때의 주의점
- 다중 상속의 문제점과 해결 방법(가상 상속 virtual 사용).
📌 8.5 C++11의 override와 final
C++11에서는 override 키워드와 final 키워드가 추가되어, 가상 함수 오버라이딩을 더 안전하게 수행할 수 있다.
📌 세부 내용
- override 키워드의 필요성
- 오버라이딩을 명확하게 선언하여 실수를 방지.
- void func() override; 사용 시, 부모 클래스에 해당 함수가 없으면 컴파일 오류 발생.
- final 키워드의 필요성
- final을 사용하면 더 이상 상속 또는 오버라이딩 불가능.
- class Derived final { ... }; → 해당 클래스를 상속 금지.
- void func() final; → 해당 함수를 재정의 금지.
📌 8.6 explicit 생성자 (C++11)
C++에서는 암시적 변환을 방지하기 위해 explicit 생성자를 사용할 수 있음.
이를 통해 예기치 않은 형 변환을 막고, 코드의 안전성을 높일 수 있다.
📌 세부 내용
- 암시적 변환(Implicit Conversion)의 문제점
- Class obj = 10; → Class(10)으로 변환되는 문제.
- explicit 키워드를 사용하여 변환 방지
- explicit 키워드를 생성자 앞에 붙이면 암시적 변환 금지.
- 예제 및 활용법
- explicit 생성자를 사용한 타입 변환 방지.
- 단일 인자 생성자에서 explicit 적용 여부에 따른 차이점.
번호 | 주제 | 설명 |
8.1 캡슐화, 상속, 다형성 | OOP의 3대 원칙 | 데이터 보호, 코드 재사용, 동적 바인딩 |
8.2 virtual 함수와 오버라이딩 | 동적 바인딩 구현 | 가상 함수 활용, 오버라이딩 구현 |
8.3 순수 가상 함수 (= 0) | 추상 클래스 및 강제 구현 | 인터페이스 역할, 다형성 적용 |
8.4 인터페이스 개념 | 추상 클래스 기반 인터페이스 | 다중 상속을 통한 인터페이스 구성 |
8.5 C++11의 override와 final | 오버라이딩의 안정성 향상 | override 사용으로 오류 방지 |
8.6 explicit 생성자 (C++11) | 암시적 변환 방지 | explicit 키워드를 통한 안전성 확보 |
📌 9. 템플릿 기초
C++의 템플릿(Template)은 일반화 프로그래밍(Generic Programming)을 가능하게 하며, 데이터 타입에 의존하지 않는 코드를 작성할 수 있도록 해준다.
템플릿을 활용하면 재사용성이 높은 코드를 작성할 수 있으며, 컴파일 타임에 타입을 결정하여 최적화된 실행 성능을 제공한다.
📌 9.1 함수 템플릿 (Function Template)
템플릿을 사용하면 데이터 타입에 의존하지 않는 함수 작성이 가능하며,
코드 중복을 줄이고, 일반화된 로직을 구현할 수 있다.
📌 세부 내용
- 템플릿 함수의 기본 개념 (template<typename T>)
- 템플릿 함수 선언 및 구현 방법
- 템플릿 함수 호출 방식 (함수 인자 타입 추론)
- 템플릿 특수화(Template Specialization)
- 다중 타입 템플릿 (template<typename T1, typename T2>) 활용법
📌 9.2 클래스 템플릿 (Class Template)
클래스 템플릿을 사용하면 타입에 의존하지 않는 클래스 정의가 가능하며,
STL(Standard Template Library) 컨테이너처럼 범용적인 데이터 구조를 구현할 수 있다.
📌 세부 내용
- 클래스 템플릿 기본 개념 (template<class T>)
- 클래스 템플릿 선언 및 객체 생성 방법
- 템플릿 멤버 함수의 정의 및 구현
- 클래스 템플릿의 특수화 (Template Specialization)
- 클래스 템플릿의 부분 특수화 (Partial Specialization)
- 템플릿과 상속 (템플릿 기반 클래스의 확장)
📌 9.3 C++17의 template<typename T> auto
C++17부터 템플릿 함수에서 반환 타입을 auto로 설정할 수 있어
반환값의 타입을 더욱 유연하게 지정할 수 있다.
이를 통해 코드 가독성이 향상되며, 더욱 강력한 타입 추론이 가능해진다.
📌 세부 내용
- template<typename T> auto의 기본 개념
- 반환 타입 자동 추론 (decltype(auto))과의 차이점
- 템플릿 함수에서 auto를 사용하여 타입 유추하기
- 람다(Lambda)와 auto를 활용한 템플릿 프로그래밍
- C++17 이전 방식과 비교 (decltype, trailing return type)
번호 | 주제 | 설명 |
9.1 함수 템플릿 | 일반화된 함수 작성 | template<typename T> 활용, 타입 추론, 특수화 |
9.2 클래스 템플릿 | 일반화된 클래스 설계 | template<class T>을 활용한 범용 클래스 작성 |
9.3 template<typename T> auto (C++17) | 자동 반환 타입 | auto를 이용한 반환 타입 추론, decltype(auto)와 비교 |
📌 10. 예외 처리
C++에서 예외 처리(Exception Handling)는 프로그램 실행 중 발생하는 오류를 안전하게 처리하는 방법이다.
이를 통해 예기치 않은 상황에서도 프로그램이 정상적으로 동작할 수 있도록 한다.
📌 10.1 try-catch 블록 (예외 처리의 기본 구조)
try-catch 블록을 사용하면 프로그램에서 예외를 감지하고 적절한 방식으로 처리 가능하다.
📌 세부 내용
- 예외 처리의 기본 개념 (try, catch)
- 여러 개의 catch 블록을 활용한 다양한 예외 처리
- 예외가 발생하지 않는 경우 catch 블록이 실행되지 않음
- 예외 객체를 통한 추가 정보 제공
- catch(...)를 활용한 범용 예외 처리
📌 10.2 throw 키워드 (예외 발생시키기)
throw 키워드를 사용하면 특정 조건에서 예외를 발생시켜 오류 처리를 강제할 수 있다.
📌 세부 내용
- throw 키워드의 기본 개념 (throw 예외객체)
- throw를 활용한 예외 강제 발생
- 사용자 정의 예외 클래스 생성 방법
- 함수에서 예외를 던지고 (throw), try-catch로 처리하는 방법
- throw;를 사용하여 예외를 다시 던지는 방법 (rethrowing)
📌 10.3 기본 예외 클래스 (std::exception, std::runtime_error)
C++ 표준 라이브러리는 예외 처리를 위한 다양한 클래스(std::exception 계열)를 제공한다.
📌 세부 내용
- 표준 예외 클래스 (std::exception, std::runtime_error, std::logic_error 등)의 개념
- what() 함수를 활용한 예외 메시지 출력
- 사용자 정의 예외 클래스를 std::exception에서 상속하여 만들기
- std::bad_alloc을 활용한 메모리 할당 예외 처리
- 라이브러리 함수(std::stoi, std::vector::at 등)에서 발생하는 표준 예외 처리 방법
번호 | 주제 | 설명 |
10.1 try-catch 블록 | 예외 감지 및 처리 | try, catch 활용, 다중 catch 처리, 범용 예외 처리 (catch(...)) |
10.2 throw 키워드 | 예외 발생 및 전달 | throw로 예외 발생, 사용자 정의 예외 클래스, throw;를 통한 재전달 |
10.3 표준 예외 클래스 | C++ 표준 예외 활용 | std::exception 계열 활용 (std::runtime_error, std::bad_alloc 등) |
📌 11. 표준 라이브러리(STL)
C++ 표준 템플릿 라이브러리(STL, Standard Template Library)는 효율적인 데이터 구조와 알고리즘을 제공하는 강력한 라이브러리이다.
이를 활용하면 자료구조를 직접 구현할 필요 없이 효율적인 컨테이너와 알고리즘을 사용할 수 있다.
📌 11.1 std::vector, std::array (동적 및 정적 배열)
📌 세부 내용
- std::vector 개념 및 동적 크기 조절
- std::vector의 주요 함수 (push_back, pop_back, size, at)
- std::array 개념 및 크기 고정 배열
- std::vector vs std::array 차이점
- 반복문을 활용한 컨테이너 순회
📌 11.2 std::map, std::unordered_map (연관 컨테이너)
📌 세부 내용
- std::map (정렬된 키-값 쌍 저장)
- std::unordered_map (해시 기반 빠른 검색)
- 삽입, 삭제, 탐색 (insert, erase, find)
- std::map vs std::unordered_map 성능 차이
- 커스텀 비교 함수 및 해시 함수 적용 방법
📌 11.3 std::set, std::unordered_set (중복 없는 집합)
📌 세부 내용
- std::set (정렬된 중복 없는 요소 저장)
- std::unordered_set (해시 기반 빠른 검색)
- 삽입, 삭제, 탐색 (insert, erase, find)
- std::set vs std::unordered_set 성능 비교
- 커스텀 정렬 및 해시 함수 적용 방법
📌 11.4 std::pair, std::tuple (C++11)
📌 세부 내용
- std::pair를 활용한 두 개의 값 저장
- std::tuple을 활용한 다중 값 저장
- std::get<>, std::tie를 이용한 요소 접근
- 구조적 바인딩을 활용한 std::tuple 해체 (C++17)
📌 11.5 std::algorithm (정렬 및 탐색 알고리즘)
📌 세부 내용
- std::sort를 활용한 정렬
- std::find를 활용한 원소 탐색
- std::for_each를 활용한 반복 처리
- std::reverse, std::min_element, std::max_element
- 람다 표현식을 활용한 커스텀 정렬
번호 | 주제 | 설명 |
11.1 std::vector, std::array | 배열 컨테이너 | 동적 크기 조절(std::vector) 및 고정 크기 배열(std::array) |
11.2 std::map, std::unordered_map | 연관 컨테이너 | 키-값 쌍 저장, 정렬(std::map) vs 해시(std::unordered_map) |
11.3 std::set, std::unordered_set | 집합 컨테이너 | 중복 없는 요소 저장, 정렬(std::set) vs 해시(std::unordered_set) |
11.4 std::pair, std::tuple | 다중 값 저장 | std::pair, std::tuple, 구조적 바인딩 활용 |
11.5 std::algorithm | 알고리즘 라이브러리 | 정렬(sort), 탐색(find), 반복 처리(for_each) |
📌 12. 최신 C++ 기능 소개
C++은 지속적인 발전을 거듭하며 새로운 기능이 추가되어 코드의 가독성을 높이고 성능을 최적화하는 기능들을 제공한다.
초급 과정에서는 각 버전별 핵심 기능을 간단히 이해하는 데 초점을 맞춘다.
📌 12.1 C++11: 주요 기능 소개
📌 세부 내용
- auto와 decltype을 활용한 타입 추론
- nullptr 도입으로 NULL보다 안전한 포인터 처리
- 스마트 포인터 (std::unique_ptr, std::shared_ptr)
- 이동 시멘틱스 (move semantics)로 불필요한 복사 방지
📌 12.2 C++14: 개선된 스마트 포인터
📌 세부 내용
- std::make_unique를 활용한 안전한 스마트 포인터 생성
- C++11에서 부족했던 기능 보완 (기본적인 문법 개선 포함)
📌 12.3 C++17: 구조적 바인딩과 if constexpr
📌 세부 내용
- 구조적 바인딩 (structured bindings)을 활용한 변수 분해
- 컴파일 타임 조건문 (if constexpr)을 통한 최적화
- 기본적인 문법 변화 및 코드 단순화
📌 12.4 C++20: 개념(concepts)과 범위 기반 for 개선
📌 세부 내용
- 템플릿에서 concepts를 활용한 타입 제약
- 향상된 범위 기반 for 루프 사용법
- 기본적인 문법 개선 (코루틴, ranges 등 간략 소개)
📌 12.5 C++23: std::expected 기본 개념
📌 세부 내용
- std::expected를 활용한 예외 처리 대체 방법
- 오류를 값으로 반환하는 방식의 개념 이해
- 기본적인 사용 예제 소개
번호 | 주제 | 설명 |
12.1 C++11 | auto, decltype, 스마트 포인터, move semantics | 타입 추론 및 메모리 관리 개선 |
12.2 C++14 | std::make_unique | 스마트 포인터 생성 방식 개선 |
12.3 C++17 | 구조적 바인딩, if constexpr | 변수 해체, 컴파일 타임 최적화 |
12.4 C++20 | concepts, 범위 기반 for 개선 | 템플릿 타입 제약, 반복문 개선 |
12.5 C++23 | std::expected | 값 기반 예외 처리 방식 |
📌 추가 내용 (심화 학습)
심화 학습에서는 C++에서 자주 사용되는 고급 기능을 다룬다.
이를 통해 더 효율적이고 모던한 C++ 코드 작성이 가능하다.
📌 1. 네임스페이스 (namespace)
📌 세부 내용
- 네임스페이스의 개념과 필요성
- 기본적인 namespace 사용법
- 중첩 네임스페이스 (namespace A::B)
- using namespace와 네임스페이스 충돌 방지
- 익명 네임스페이스 (namespace {}) 활용법
- C++17의 inline namespace와 C++20의 namespace alias 개선
📌 2. 파일 입출력 (fstream)
📌 세부 내용
- 파일 스트림 (std::ifstream, std::ofstream, std::fstream) 기본 사용법
- 텍스트 파일 읽기/쓰기 (open(), close(), getline())
- 바이너리 파일 읽기/쓰기 (read(), write())
- 파일 스트림의 예외 처리 (exceptions(), fail())
- 파일을 활용한 데이터 저장 및 로깅 구현
📌 3. 람다 함수 (lambda expressions)
📌 세부 내용
- 람다 함수 기본 문법 ([](){})
- 캡처 리스트 ([=], [&], [this]) 활용법
- 람다 함수의 반환 타입 (-> Type) 지정 방법
- std::function을 활용한 람다 함수 저장
- C++14의 제네릭 람다 (auto 매개변수)
- C++20의 constexpr 람다와 template 람다
📌 4. 비동기 프로그래밍 (std::thread, std::async)
📌 세부 내용
- C++에서의 멀티스레딩 개념과 필요성
- std::thread를 활용한 멀티스레딩 기초
- 스레드 동기화 (std::mutex, std::lock_guard)
- 비동기 실행 (std::async, std::future) 개념
- C++20의 std::jthread와 자동 종료 기능
- 멀티스레딩에서 발생할 수 있는 문제점 (데드락, 경쟁 상태) 해결 방법
번호 | 주제 | 설명 |
1. 네임스페이스 | namespace, using namespace, inline namespace | 코드 충돌 방지 및 네임스페이스 활용법 |
2. 파일 입출력 | std::ifstream, std::ofstream, std::fstream | 텍스트 및 바이너리 파일 읽기/쓰기 |
3. 람다 함수 | [](){}, 캡처 리스트, std::function | 함수 객체를 간단하게 정의하는 방법 |
4. 비동기 프로그래밍 | std::thread, std::async, std::mutex | 병렬 프로그래밍과 동기화 기법 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
모던 C++(Modern C++)의 정의와 주요 특징 (0) | 2025.03.11 |
---|---|
C++ 초급 - 추가 내용 (심화 학습) (4 - 비동기 프로그래밍 (std::thread, std::async)) (0) | 2025.02.22 |
C++ 초급 - 추가 내용 (심화 학습) (3 - 람다 함수 (lambda expressions)) (0) | 2025.02.22 |
C++ 초급 - 추가 내용 (심화 학습) (2 - 파일 입출력 (fstream)) (0) | 2025.02.22 |
C++ 초급 - 추가 내용 (심화 학습) (1 - 네임스페이스 (namespace)) (0) | 2025.02.22 |