일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- dart 언어
- jupyter
- 플러터
- jupyter lab
- git
- 도커
- 포인터
- gitlab
- github
- Unity
- C언어 포인터
- 다트 언어
- 구조체
- 깃
- HTML
- Algorithm
- c# winform
- 유니티
- Python
- c#
- c# 윈폼
- c# 추상 클래스
- Flutter
- c언어
- Data Structure
- vim
- C++
- docker
- C# delegate
- Houdini
- Today
- Total
목록Programming (313)
nomad-programmer
제네레이터는 제네레이터 객체에서 __next__ 메서드를 호출할 때마다 함수 안의 yield 까지 코드를 실행하며 yield에서 값을 발생시킨다(generate). 그래서 이름이 제네레이터이다. for와 제네레이터 for 반복문은 반복할 때마다 __next__ 를 호출하므로 yield에서 발생시킨 값을 가져온다. 그리고 StopIteration 예외가 발생하면 반복을 끝낸다. 참고로 제네레이터 객체에서 __iter__를 호출하면 self를 반환하므로 같은 객체가 나온다. (제네레이터 함수 호출 > 제네레이터 객체 > __iter__는 self 반환 > 제네레이터 객체) 그런데 generate라는 키워드를 사용하면 되지 왜 yield라고 이름을 지었을까? yield는 생산하다라는 뜻과 양보하다라는 뜻도 가..
__iter__, __next__ 메서드를 구현하여 직접 이터레이터를 만들어보자. 간단하게 range(횟수)처럼 동작하는 이터레이터다. class Counter: def __init__(self, stop: int) -> None: self.__current = 0 self.__stop = stop def __iter__(self): return self def __next__(self) -> int: if self.__current < self.__stop: r = self.__current self.__current += 1 return r else: raise StopIteration if __name__ == '__main__': for i in Counter(3): print(i, end=' '..
컴퓨테이셔널 씽킹은 4가지로 되어 있다. 분해: 복잡한 문제를 작은 문제로 나눈다. 패턴 인식: 문제 안에서 유사성을 발견한다. 추상화: 문제의 핵심에만 집중하고 부차적인 것은 제외한다. 알고리즘: 이렇게 정의한 문제를 해결하는 절차이다. (일반화와 모델링은 여기에 포함) 복잡한 문제를 해결하는 것은 어렵지만, 작은 문제를 해결하는 것은 비교적 쉽다. 작은 문제를 해결하다 보면 복잡한 문제를 해결하게 된다. 컴퓨터 공학에서 배우는 알고리즘은 대부분 정형화된 문제에 대해 검증된 해법을 제시하는 과목이다. 현실에서 컴퓨터로 해결하려는 문제는 정형화된 문제가 아니라 비정형화된 문제가 더 많다. 그래서 비정형화된 문제를 컴퓨터로 해결하는 과정. 즉, 문제를 이해하고 분해, 패턴 인식, 추상화, 알고리즘 작성까지..
// 예를 들어 int타입의 최대 값을 구하고 싶다면 헤더 파일을 포함시킨 후 // numeric_limits::max() 처럼 호출하면 된다. #include #include #include using namespace std; template void ShowRange(const char* typeName) { cout
STL은 이름 그대로 템플릿을 사용해서 만들어진 라이브러리다. STL은 일반적으로 많이 사용하는 클래스와 함수들이 만들어져 있는데, 예를 들어 링크드 리스트 클래스, 동적 배열 클래스, 정렬 함수, 검색 함수 등과 같이 범용적인 클래스와 함수들이 있다. 또한 이런 클래스와 함수들은 템플릿으로 만들어져 있기 때문에 확장이 용이하다. STL은 사용함으로써 얻을 수 있는 장점들이 있다. 첫번째, STL은 표준이다. 이는 지구 반대편에 있는 개발자도 나와 똑같은 클래스와 함수를 사용한다는 것을 의미한다. 때문에 상대방이 작성해놓은 코드를 쉽게 알아볼 수 있다. 두번째, STL은 전문가들이 만들어 놓은 것이기 때문에 직접 만든 것보다 효율적이고 안전하다. 물론 엄청난 실력자라 STL에 있는 것보다 훌륭하게 만들 ..
C++의 코딩 표준에 대해 알아보자. https://docs.popekim.com/ko/coding-standards/cpp C++ 코딩 표준 | 포프의 문서창고 제대로 대우받는 개발자 | 부족한 컴공지식 배우기 | MIT급 컴공인강 최저임금으로 고통받는 일회성 프로그래머는 그만! POCU 아카데미가 올해 연봉협상을 책임지겠습니다! docs.popekim.com
템플릿은 C++에서 없어서는 안될 아주 중요한 기능인데 템플릿을 사용하면 컴파일러가 개발자를 대신해서 클래스나 함수를 만들어내게 할 수 있다. 그리고 C++에는 이러한 템플릿을 사용해서 만들어진 다양한 클래스와 함수들을 STL이라는 이름으로 제공하고 있다. 왜 템플릿을 사용해야 할까? 템플릿은 C++에서 가장 눈에 띄는 기능이라고 할 수 있다. C++의 다른 기능들은 Java와 C# 같은 객체지향 언어에서도 대부분 지원하는 것들이지만 템플릿 만큼은 C++이 아니면 찾아볼 수 없는 독특한 기능이기 때문이다. 템플릿은 함수를 자동으로 생성하는 것에 더해서 클래스까지 자동으로 생성해줄 수 있다. 그리고 이 두 가지를 구분하기 위해서 템플릿 클래스, 템플릿 함수 등으로 나누어 부르게 된다. 템플릿 클래스 #in..
C++ 개발자가 선호하는 11가지 라이브러리를 소개한다. 1. 액티브 템플릿 라이브러리 (Active Template Library, ATL) 액티브 템플릿 라이브러리(Active Template Library, ATL)는 COM(구성 요소 개체 모델) 개체를 만들 수 있는 템플릿 기반 C++ 클래스의 세트이다. https://learn.microsoft.com/ko-kr/cpp/atl/active-template-library-atl-concepts?view=msvc-170 ATL(액티브 템플릿 라이브러리) 개념 자세한 정보: ATL(활성 템플릿 라이브러리) 개념 learn.microsoft.com 2. 아시오 C++ 라이브러리 (Asio) asio는 네트워크 프로그래밍을 위한 C++ 라이브러리다. 오..
프로젝트의 크기가 커지게 되면 소스 파일의 수도 많아지고, 또 소스 파일들 안에서 정의도니 수많은 변수, 함수, 구조체, 클래스, 열거체 등이 존재하게 된다. 이런 경우에는 관련된 코드별로 그룹을 나누어서 관리하면매우 효율적인데 이때 네임스페이스(namespace)가 관련된 코드를 나누어 담을 수 있는 논리적인 가방의 역할을 한다. 왜 네임 스페이스를 사용해야 할까? 실세 현장에서 개발하는 프로젝트는 수백 개 이상의 소스 파일로 이루어져 있다. 그리고 이 파일들 안에는 수천, 수만 개의 이름이 존재한다. 변수, 함수, 클래스, 구조체, 열거체, 타입 재정의(typedef)를 사용할 때마다 새로운 이름이 생겨나는 것이므로 충분히 수만 개에 달할 수 있다. 중요한 것은 이렇게 정의한 이름들이 모두 한 공간에..
형 변환을 할 때는 괄호를 사용했다. 이 방법은 C언어에서 사용하던 방식이다. C++에서는 이를 대체할 수 있는 4가지 종류의 형변환 연산자가 추가되었다. 이 연산자들을 살펴보자. C++ 스타일의 형 변환을 사용해야 하는 이유? 한 마디로 말해 C 스타일의 형변환은 두 가지 문제점이 있다. C 스타일의 형 변환은 눈에 잘 띄지도 않고 툴을 사용해서 찾아내기도 힘들다. 왜냐하면 형변환 말고도 괄호를 사용하는 부분이 많기 때문이다. C++ 스타일의 형 변환은 눈에 잘 띄는 외관을 가지고 있기 때문에 형변환을 수행하는 코드를 한눈에 알아 볼 수 있다. 그렇다면 눈에 잘 띄지 않는 것이 왜 단점이 될까? 그것은 명시적인 형 변환은 언제나 문제의 소지가 있기 때문이다. 명시적인 형변환을 수행한다는 것은 암묵적인 ..
구조적 예외 처리는 예외 상황을 효율적으로 처리할 수 있게 도와주지만 잘못 사용하는 경우에는 화를 입을 수도 있다. 구조적 예외 처리에는 어떤 문제점이 존재하고 또 어떻게 해결해야 하는지 알아보자. 리소스를 정리하기 전 예외가 발생한 경우의 문제점 구조적 예외 처리에서 가장 빈번하게 일어나는 문제는 리소스를 정리하기 전에 함수가 종료되는 경우다. 다음의 예제는 예외로 인해서 할당된 메모리가 해제되지 못하는 문제점을 가지고 있다. #pragma warning(disable: 4996) #include using namespace std; void A(); void B(); int main(void) { try { A(); } catch (const char* ex) { cout
예외 처리가 프로와 아마추어를 구분하는 기준이 될 수 있다는 점을 기억하자. 반환 값을 사용한 예외 처리 다음의 예제를 살펴보자. // DynamicArray.h #pragma once class DynamicArray { public: DynamicArray(int arraySize); ~DynamicArray(); bool SetAt(int intdex, int value); int GetAt(int index) const; int GetSize() const; protected: int* arr; int size; }; // DynamicArray.cpp #include "DynamicArray.h" DynamicArray::DynamicArray(int arraySize) { arr = new i..
순수 가상 함수 부모 클래스의 멤버 함수를 자식 클래스에서 재정의하는 것을 오버라이딩(overriding)이라고 부른다. 이 개념은 오버로딩과 혼동하지 않게 주의해야 한다. 오버라이딩과 관련한 몇 가지 주제를 살펴보는데, 먼저 순수 가상 함수를 살펴보자. 순수 가상 함수(Pure Virtual Functions)는 가상 함수의 한 종류다. 순수 가상 함수는 왜 사용할까? 순수 가상 함수를 만드는 방법은 간단하다. 가산 함수의 선언 뒤에 다음과 같이 '=0'을 붙여주면 된다. 마치 함수에 0값을 대입한 것처럼 보인다. virtual void Draw() const = 0; 순수 가상 함수는 함수의 정의 부분이 필요하지 않다. 위와 같이 함수의 원형망 가지고 있는 함수가 바로 순수 가상 함수다. 그렇다면 하..
언제 가상 함수가 필요할까? 가상 함수의 필요성을 알아보려면 소스 코드를 보는 것이 가장 좋다. 다음의 예제를 보자. #include using namespace std; class Shape{ public: void Move(double x, double y); void Draw() const; Shape(); Shape(double x, double y); protected: double _x, _y; }; Shape::Shape(): _x(0), _y(0) {} Shape::Shape(double x, double y): _x(x), _y(y) {} void Shape::Move(double x, double y){ _x = x; _y = y; } void Shape::Draw() const{ cout
연산자 오버로딩에는 다음 두 가지가 있다. 첫째, 멤버 함수를 이용한 연산자 오버로딩 둘째, 전역 함수를 이용한 연산자 오버로딩 일반적으로 멤버 함수를 이용한 연산자 오버로딩을 사용한다. 멤버 함수를 이용한 연산자 오버로딩을 사용할 수 없을 때는 전역 함수 연산자 오버로딩을 사용한다. 멤버 함수를 이용한 연산자 오버로딩을 사용할 수 없는 경우 이항 연산의 왼쪽 항이 연산자 오버로딩 객체가 아니면 멤버 함수를 이용한 연산자 오버로딩을 이용할 수 없다. 이항 연산의 왼쪽 객체를 기준으로 연산자 오버로딩 멤버 함수를 호출하기 때문이다. 예를 들어 보자. class Point { ... }; int main() { Point p1(1, 2), pt2(3, 4); pt1 + pt2; // pt1.operator+..
다중 상속(Multiple Inheritance)은 두 개 이상의 부모 클래스를 동시에 상속하는 경우를 말한다. 왜 다중 상속을 사용해야 할까 학생 정보를 관리하는 프로그램을 작성한다고 하자. 기본적으로 학부생과 대학원생의 정보를 관리하는 2개의 클래스를 생각해볼 수 있다. 그리고 기숙사생의 정보를 관리하는 클래스도 생각해볼 수 있다. 그렇다면 학부생이면서 동시에 기숙사생인 학생의 정보는 어떤 클래스에 의해서 관리되어야 할까. 학부생 클래스 아니면 기숙사생 클래스? 바로 이런 경우에 다중 상속을 사용할 수 있다. 학부생 클래스와 기숙사생 클래스를 모두 상속해서 학부생이면서 기숙사생인 학생의 정보를 관리하는 클래스를 만들 수 있다. 다중 상속의 사용 다음 예제에는 세 개의 클래스가 등장한다. 각각 학부생 ..
접근 제어 키워드 public: 모든 곳으로부터의 접근 허용 protected: 자식 클래스의 멤버 함수로부터의 접근만 허용 private: 자신의 멤버 함수 외에는 접근 불가 다음 예제를 보며 이 키워드가 의미하는 바를 구체적으로 확인해보자. #include using namespace std; class Parent{ private: int priv; protected: int prot; public: int publ; }; class Child : public Parent { void AccessParents(){ int n; // 부모의 멤버에 접근 시도 n = prev; // 실패 n = prot; // 성공 n = publ; // 성공 } }; int main(int argc, const ch..
단항 연산자 오버로딩 오버로딩이 가능한 단항 연산자는 !, &, ~, *, +, -, ++, -- 형 변환 연산자이다. ++, --연산자로 단항 연산자 오버로딩에 대해 알아보자. ++, -- 연산자 오버로딩 ++ 연산자는 전위 ++ 연산자와 후위 ++ 연산자가 있습니다. 컴파일러와 약속된 함수는 operator++() 와 operator++(int) 입니다. #include using namespace std; class Point { public: Point(const int x, const int y); ~Point(); void Print() const; // 전위 ++, -- const Point& operator++(); const Point& operator--(); // 후위 ++, -- c..
const 멤버 함수는 멤버 함수 내에서 객체의 멤버 변수를 변경하지 않는다는 것을 보장하는 함수이다. 따라서 const 객체는 const 멤버 함수만 호출할 수 있다. const 멤버 함수에서 멤버 변수를 변경하면 컴파일 에러가 발생한다. 사실 자신의 멤버를 변경하지 않는 멤버 함수는 모두 const 멤버 함수여야만 한다. 다음은 cosnt 멤버 함수 예제이다. class Point{ public: Point(int _x=0, int _y=0) : x(_x), y(_y) {} int GetX() const { return x; } int GetY() const { return y; } void SetX(int _x) { x = _x; } void SetY(int _y) { y = _y; } void P..