프로그래밍 언어

    C# 인터페이스 (interface)

    인터페이스는 계약이라고 볼 수 있다. interface는 클래스가 아니기 때문에 다중 상속이 가능하다. 인터페이스는 추상 메서드만 0개 이상 담고 있는 추상 클래스라고 봐도 무방하다. 특징 Method만을 포함할 수 있다. 비어 있는 인터페이스 정의가 가능하다. 자식 클래스에서 구현할 때, 반드시 public 접근 제한사를 명시해야 한다. (인터페이스명을 직접 붙이면 생략 가능) 인터페이스명을 직접 붙이는 경우에는 반드시 인터페이스로 형변환해야 호출이 가능하다. C#에서는 property가 메서드로 구현되기 때문에 인터페이스에 포함 가능하다. interface IFlyable { void Fly(); } interface IRunnable { void Run(); void Stop(); } abstrac..

    C# 클래스 접근 제한자 (Access Modifier)

    접근 제한자에는 public, protected, internal, private가 있다. 클래스 기본형은 internal이다. 접근 제한자 설명 private 클래스 내부에서만 접근이 가능하다. public 모든 곳에서 해당 멤버로 접근이 가능하다. internal 같은 어셈블리에서만 public으로 접근이 가능하다. protected 클래스 외부에서 접근할 수 없으나 파생 클래스에서는 접근이 가능하다. protected internal 같은 어셈블리에서만 protected으로 접근이 가능하다. using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace ConsoleApplication1 {..

    C++ 클래스 접근 제한자 (Access Modifier)

    public, private, protected 바로 이 3가지이고 쓰여지는 이유는 객체지향 프로그래밍의 중요한 개념 중 하나는 데이터 숨김(은닉) 때문이다. 클래스 내에 멤버에 대한 접근 제한자를 두지 않으면 기본적으로 private이다. 구조체 멤버에 대한 기본적인 접근 제한자는 public이다. friend 키워드는 private와 protected의 원칙을 깨트림으로서 코드의 직관성과 흐름 파악을 복잡하게하는 goto같은 존재이다. friend 관련 글 참고 public public으로 선언된 데이터 멤버 및 멤버함수는 . 연산자를 사용하여 프로그램의 아무곳에서나 액세스 할 수 있다. private 클래스 멤버를 private으로 선언하면 해당 멤버는 오직 클래스 내부에서 접근할 수 있다, 외부의..

    C# 힙 구조 (Heap)

    스택은 단순히 데이터를 넣고 뺄 수 있는 구조이며, System.ValueType을 상속하는 기본 데이터형(int, long, bool 등)만 저장할 수 있다. 힙은 예약된 주소 공간을 뜻한다. 최초에 프로세스가 초기화될 때 시스템은 프로세스 주고 공간 내에 하나의 힙을 생성한다. 이 힙을 프로세스의 기본 힙이라 하며, 기본 할당 크기는 1M로 정해져있다. 닷넷에서는 가비지 컬렉터가 자원을 관리하기 때문에 힙에 대한 함수를 직접 제공하지 않지만 Win32 API GetProcessHeap() 사용하여 현재 프로세스의 힙을 가져올 수 있다. using System.Runtime.InteropServices; public unsafe class Memory { static int ph = GetProcess..

    C++ 스마트 포인터 (Smart Pointer)

    C++ 프로그램에서 new 키워드를 사용하여 동적으로 할당받은 메모리는, 반드시 delete 키워드를 사용하여 해제해야 하는데, 만약 해제하지 않고 넘어갈 경우에 메모리 누수 (Memory Leak) 문제가 발생해서 프로그램의 안정성을 보장받을 수 없게 된다. 스마트 포인터는 클래스 템플릿으로서 사용이 끝난 메모리를 자동으로 해제해주어 메모리 누수 문제가 일어나지 않도록 해준다. 동작하는 방법은 기본 포인터 (Raw Pointer)가 실제 메모리를 가리키도록 초기화한 후에, 기본 포인터를 스마트 포인터에 대입하여 사용된다. 스마트 포인터의 종류 C++ 11 표준 이전에도 auto_ptr 이라는 스마트 포인터로 작업을 처리했었는데, 현재 모던 C++ 이라 불리우는 C++ 11 이상의 표준에 대해서는 aut..

    C# 구조체 (struct) 클래스 (class) 차이

    struct 코드 struct Point { public int X; public int Y; public int Z; public Point(int x, int y, int z) { this.X = x; this.Y = y; this.Z = z; } public static Point operator +(Point p1, Point p2) { return new Point(p1.X + p2.X, p1.Y + p2.Y, p1.Z + p2.Z); } public String toString() { return "x: " + X + ", y: " + Y + ", z: " + Z; } } class 코드 class Point { public int X; public int Y; public int Z; pub..

    C++ 바이트 패딩 (Byte Padding)

    왜 컴파일러는 구조체의 메모리를 정렬해 놓을까? 적은 수의 컴파일러는 구조체의 필드를 메모리에 위치시킬 때, 중간 빈 공간 없이 쭉 이어서 할당한다. 하지만 대부분의 컴파일러는 성능 향상을 위해 cpu가 접근하기 쉬운 위치에 필드를 배치하는 데 이를 구조체 패딩이라고 한다. 그리고 중간 빈 공간에 들어간 것을 패딩 비트라고 한다. 참고로 os 32bit 환경에서는 4byte packing 방식이 빠르고 os 64bit 환경에서는 8byte packing 방식이 빠르다고 한다. 왜 빠를까? 패딩 비트가 없을 경우 어떤 일이 일어나는지 생각해보자. cpu는 메모리를 읽어올 때 한 번에 32bit os : 4byte 혹은 64bit os : 8byte를 읽어온다. class Test { char _c1; //..

    C++ 참조 대상 수 (Reference Counting)

    Reference Counting은 객체의 소유권 관리( = 라이프 사이클 )의 방법 중 하나로 객체를 참조(포인팅) 하고 있는 횟수를 추적하여 그 횟수가 0이 되면 메모리에서 해제(소멸)한다. 대부분의 Managed Language (python, c#, swift등 메모리 관리를 직접 하지 않는 언어 ) 에서 널리 사용되고 있다. 장점 - 메모리를 직접 해제하는 번거로움이 사라진다. - 객체의 소유권을 공유할 수 있다 - 객체 관리 매커니즘이 비교적 단순해서 빠르다. (Garbage Collection) 단점 - 순환 참조 문제가 있다. c++ 에서의 구현방식에는 크게 두가지가 있다. Intrusive Reference Counting (침습성 참조 카운팅) - 객체에 대한 참조 카운트가 "내장" 되..

    C++ 순환 참조 (Circular Dependency) & 데드락

    순환 참조 문제는 비단 Reference Counting 뿐만이 아니라 다양한 영역에서 이를 피하는것이 매우 중요하다. 설계적 관점에서, 서로 참조를 하는 두 객체가 있다면 의존 관계가 양방향이 되고 의존성(Dependency)이 커지기 때문에 코드 관리에 어려움이 생긴다. 멀티 스레드( or 프로세스 ) 환경에서는 Resource를 점유한 상태로 새 Resource의 요청이 "순환"하는 경우 교착 상태(Dead Lock)에 빠지게 된다. class ObjectA { public: ObjectA() { std::cout

    C++ 4가지 타입의 캐스팅

    1. static_cast C언어의 타입 캐스팅과 동일하다. 논리적으로 변환 가능한 타입만 변환한다. 안에는 타입을 지정하고, ()안에는 캐스팅할 대상을 지정한다. 업캐스팅 다운캐스팅 참고 2. const_cast 변수, 포인터 변수 또는 참조형의 상수성을 추가 / 제거를 위한 캐스팅에만 사용. class Parent { int mVal = 0; public: Parent() = default; Parent(int Val) : mVal(Val) { } public: void Print() { cout