전체 글 36

특수 멤버 함수의 정의 규칙 (The rule of five)

The rule of five는 "소멸자, 복사생성자, 복사대입연산자, 이동생성자, 이동대입연산자"라는 다섯 가지 특수 멤버 함수 중 하나라도 정의한다면, 나머지에 대한 정의와 처리도 고민해야 한다는 원칙이다.이 다섯 가지 특수 멤버 함수는 서로 긴밀하게 관련되어 있으며, 그렇기에 Cpp 컴파일러는 개발자가 특정한 상황에 특정한 특수 멤버 함수를 정의하지 않으면 이에 대한 기본 형태를 자동으로 생성해버린다. 실제로 컴파일러의 클래스 최적화는 훨씬 복잡하고 다양한 형태로 나타난다고 한다. 개념적인 차원에서 이해하자.기본적으로 Cpp 표준에서 권장하는 방식은 5가지 중 하나라도 직접 정의했으면, 나머지도 직접 정의하라는 것이다. 이는 예상치 못한 동작을 예방하기 위함이기도 하고, 의사를 명확히 밝혀 협업자와..

🛠 C, C++/문법 2025.06.15

function, mem_fn, bind

모두 헤더에서 정의한다.std::function함수 포인터의 래퍼 객체. 모든 종류의 Callable 타입을 가리킬 수 있다.예를 들면 함수, 멤버 함수, 함수 포인터, 람다, 함수 객체 등. 템플릿 인자로 반환형(매개변수) 형태의 서명을 전달한다.int FloatToInt(float value){ return static_cast(value);}int main(){ std::function func = FloatToInt; int value = func(3.14f);} std::mem_fn멤버 함수의 경우, 구체적인 인스턴스를 통해서만 호출이 가능하므로 위와 같이 일반적인 형태로 함수 포인터가 가리키도록 할 수 없다. std::function이 멤버 함수를 가리키려면 람다로 인스턴스..

🛠 C, C++/문법 2025.05.14

friend

외부의 클래스나 함수가 해당 클래스에 public으로 접근할 수 있도록 강제하는 키워드.편리하지만 캡슐화를 위반하는 위험한 키워드이다. 난발하지 않도록 하자.// 외부의 함수void Func(int x);// 외부의 클래스class Foo{ ... };class Bar{ friend void Func(int); // 특정 함수에 대한 friend화 friend class Foo; // 특정 클래스 전체에 대한 friend화 friend void Foo::Func(); // 특정 클래스의 특정 메서드에 대한 friend화 // 이제 friend로 지정된 범위에선 Bar의 모든 멤버가 public인 것처럼 접근할 수 있다.}; friend를 붙이고 그 자리에서 바로 함수나 클래스를 정의..

🛠 C, C++/문법 2025.04.27

constexpr

정의객체 혹은 함수의 리턴값을 컴파일 타임에 알 수 있는 상수식으로 만드는 키워드.컴파일러가 컴파일 타임에 어떤 식의 값을 결정할 수 있다면, 해당 식을 상수식(Constant expression)이라고 한다. 특히 정수 상수식은 쓰임이 굉장히 많다.int arr[size]; // 배열의 크기 size는 상수식이어야 한다.template struct A { ... };A a; // 템플릿은 컴파일 타임에 생성되므로 템플릿 인자 number는 상수식이어야 한다.enum Fruit { Apple = number, Grape, Berry }; // enum 값 number는 상수식이어야 한다.쓰임constexpr 키워드가 붙은 변수는 그 자체로 상수식이 된다. 따라서 담기는 값은 컴파일 타임에 결정될 수 있..

🛠 C, C++/문법 2025.04.27

concept, requires

C++20에서 추가된 템플릿 메타 프로그래밍을 위한 도구.requires 키워드로 올 수 있는 템플릿 타입의 조건을 규정하고(어떤 타입이 올 수 있는지 정의할 뿐 아니라, 매개변수에 의미론적(semantic) 제약을 가할 수도 있다), concept로 이를 캡슐화할 수 있다. concept캡슐화된 제약 조건 덩어리.컴파일 타임에 결정되는 bool을 반환하거나 그러한 값으로 귀결될 수 있어야 한다.constexpr, consteval 키워드로 bool 타입을 반환하는 컴파일 타임 함수를 만들어 사용할 수도 있고, , 헤더에 정의된 제네릭 함수들을 써도 된다.형식 제약 컨셉템플릿 타입이 '어떤 타입'이어야 한다는 형식 제약을 규정한다.concept 이름 = 형식 제약 꼴로 선언하며, 컴파일 타임에 boo..

🛠 C, C++/문법 2025.04.27

포인터와 배열

C++에선 훨씬 쉽고 편리하며 직관적인 가변 길이 배열 STL 컨테이너를 사용하도록 하자. 배열과 포인터C/C++에서 배열은 특정한 크기의 할당된 메모리 블록을 의미한다. 이 때 배열명은 특별한 의미를 가진다.일반적으로 배열명 arr은 &arr[0] 즉 배열의 첫 번째 요소의 주소를 가리키는 포인터로 암시적 변환된다.단, 아래의 상황에선 예외로 배열 전체를 의미한다.sizeof(arr) 은 배열의 전체 크기를 반환한다.&arr 은 '배열 전체의 시작 주소'를 의미한다. 따라서 &arr + 1은 '배열 전체의 다음 번지'를 가리킨다.이 차이 때문에 다소 헷갈리는 문법이 된다. 다음은 배열명에 대한 주소 연산이 가지는 의미이다.// int arr[4];arr -> 첫 번째 요소의 주소 (&arr[0])&ar..

🛠 C, C++/문법 2025.04.27

가상 함수 (Virtual function)

OOP의 핵심인 다형성, 그 중에서도 가장 중요하다고 할 수 있는 서브타입 다형성(런타임 다형성, 오버라이딩)을 구현하기 위한 개념. C++에선 부모 클래스의 함수 서명을 자식 클래스에서 그대로 사용할 경우, 부모 클래스의 함수는 숨겨지게 된다. 예컨대 Foo() 라는 함수가 부모와 자식 모두에 존재하면, 자식 객체를 통해 Foo()를 호출하면 자식의 Foo()가 호출되게 된다. 물론 그렇다고 부모의 Foo() 함수가 사라진 것은 아니다. 부모의 타입을 명시하여 접근하는 것으로 호출은 가능하다. (물론, 호출되는 위치에서 접근이 가능하다면) 문제는 부모 타입 포인터가 기본적으로 부모 타입의 함수에만 접근할 수 있다는 데에 있다. 다형성을 활용하려면 부모 타입 포인터가 업캐스팅된 자식 타입 객체를 가리키게..

🛠 C, C++/문법 2025.04.20

객체와 함수를 은닉하기

함수와 객체를 외부로 노출시켜도 되는지, 노출시켜야 하는지 판단하는 것은 설계에 있어 매우 중요하다. 꼭 필요한 게 아니라면 일단 숨겨놓는 것을 기본으로 삼는 것이 맞다. 사용자는 언제 어느 때 어떤 행동을 취할 지 누구도 알 수 없으므로, 최대한 숨기고 접근하지 못 하게 만들어 예외 상황을 원천 차단하는 것이 좋은 설계다. 은닉하는 방법C++ 기준이다.private 접근 지정자 사용하기노출되지 않아야 하는 멤버는 private 접근 지정자를 통해 은닉한다.namespace 사용하기네임스페이스를 활용하면 접근 난이도를 높혀 일반 사용자의 접근을 차단할 수 있다.// 코어 개발자만 사용하는 네임 스페이스로 감싸는 예시// 네임스페이스를 명시하고 접근해야 하므로 접근 난도가 높아지고, 자연히 일반 사용자의..

서비스 로케이터 패턴 (Service locator pattern)

개념 여러 기능들을 '서비스 로케이터'라는 전역 클래스를 통해 관리하고 제공하는 디자인 패턴.각각의 기능을 제공하는 객체들을 서비스라고 부르며, 서비스 로케이터에 타입 또는 이름으로 서비스 객체를 등록하고, 필요한 곳에서 이를 요청하여 받아 사용하는 것이 골자이다. 개념도 간단하고 구현하기도 쉽다. 다만 구체적인 구현 방식은 하기 나름이라 매우 다양한 형태로 나타날 수 있다. 이 패턴을 사용하는 목적은 기본적으로 객체 간 의존성을 최소화하고, 생명주기의 관리마저 서비스 로케이터를 통해 쉽게 수행하는 것에 있다.의존성을 줄이기 위한 방법론이란 점에서 의존성 주입 패턴과 자주 비교된다. 결론만 말해 서비스 로케이터 패턴은 의존성 주입 패턴보다 당장 구현하기는 더 쉽고 직관적이나, 의존성을 명확하게 드러내는 ..

의존성 주입 패턴 (Dependency injection pattern)

고수준 모듈이 저수준 모듈을 사용할 때 이를 직접 생성하거나 제3자를 통해 찾아오는 대신,고수준 모듈을 생성 또는 초기화하는 외부로부터 저수준 모듈을 '주입받아' 사용하는 패턴. 핵심은 의존성을 외부에서 동적으로 만들어내고 관리하는 것이다. 기본적으로 의존성 역전 원칙이 지켜진다는 전제로 구현되며, (1) 확장과 변경에 용이하게 하고, (2) 의존성을 명시적으로 드러내기 위해 사용한다. 저수준 모듈을 외부에서 생성 또는 가져와 주입하기 때문에 보통은 해당 모듈의 수명까지 외부에서 관리하게 된다. 생성자 주입으로 주입된 객체를 주입의 대상만 사용하게끔 만들고 대상이 소멸할 때 주입된 객체도 같이 소멸하게 하는 방법도 있겠지만, 직관성이 크게 떨어지고 동적으로 의존성을 관리하는 의미가 퇴색되므로 좋은 방법이..