프로그래밍/C++2012. 4. 25. 11:55

1. cout, endl의 원리

 

cout은 원래 객체이며, endl의 경우 함수이다.  아래는 cout과 endl를 구현해 본 소스코드이다.

 

추가로 tab이나 two_endl의 사용자정의 함수도 추가했다. 

 

그럼 이게 기존거랑 충돌이 나느냐? 아래를 보자.

위와 같이 우리가 만든 함수들도 기존 std 네임스페이스와 같이 쓸 수 있다.

 

cout은 c와 달리 출력 형태가 무엇인지 정해주지 않아도 된다. 그렇다면 사용자 정의 객체 일 경우 어떻게 해야 할까?

아래는 사용자 정의 객체인 Point를 만든 코드이다.

 

cout << p;  이 부분은 결국 cout.operator<<(Point)가 있으면 된다.

 

만약 namespace를 쓴다면, 어떨까? cout은 이미 라이브러리에서 정의된 것인데, Graphic::을 붙일 수 없지 않은가?

그래서 2일차에서 나왔던 키네그 룩업이라는 기법을 써서, 어차피 Point라는 객체가 존재하는 namespace를 찾아서 쓸 수 있게 하는 것이다.

이런 문법들이 왜 이렇게 설계되었는지 더 자세히 알고 싶으면, Annoted Reference Manual : C++을 참조하라.

 

 

2. 변환 연산자

 

 

 

변환 연산자를 생성하면 된다.  변환 생성자도 추가됐다.

 

 

 

 

 

 

3. new 연산자 이야기

 

 

new를 오버로딩하는 것도 가능하다.

 

memory leak 검사하기

 

 

placement new 개념

// placement new 개념
// 1. 기존의 메모리에 대해서 생성자를 호출할 때 사용하는 기술
// 2. new(기존메모리 주소) 타입;
// 3. C로  할당한 메모리(공유메모리등)을 객체처럼 사용하려고...
// 4. 또는 Template을 활용한 고성능 라이브러리 만들 때 주로 사용
//    안드로이드의 typehelpers.h 가 이 기술 사

 

분명히 new에서는 메모리 할당을 하지 않았음에도 불고하고, 객체를 리턴함으로써 생성자/소멸자를 호출한다.(확인)

 

 

 

 

안드로이드에서는 프로세스간 Binder를 써서 통신하는데, 이때 쓰는게 mmap이다. 이와 비슷하게

 

 

이제 new와 예외처리에 대해서 알아보자.

 

멀쩡해 보이나?  1998년 이후, new가 실패 했을 경우, 더 이상 0을 리턴하지 않는다.

 

대신 다음과 같이 try... catch블록을 써서 체크해야 한다.

 

 

 

만약 아래와 같이 메모리가 부족하면, p2의 생성자는 소멸이 되는가??

 

안된다. 완전하게 끝난 생성자만 소멸이 가능하다.

 

그래서 두가지 해결책이 있다.

첫째로 스마트 포인터를 사용한다.

 

두번째로 생성자에서 자원을 할당하지 말고 자원할당 전용함수를 만들어 사용한다.

 

전체적인 소스는 다음과 같다.

 

 

4. 함수객체

 

함수객체에 대해서 알아보자.

 

예제처럼, 객체를 함수처럼 연산자 오버로딩을 통해서 사용할 수 있다.

 

전에 함수포인터는 inline 치환이 불가능했었는데, 함수객체를 사용하면, 가능하게 된다.(예제만 설명하느라 컴파일은 안된다)

함수객체의 장점은 즉, inline함수를 쓸 수 있으니, 빠르다는 점이 있겠다

 

sort를 통해서 함수객체에 대해서 더 알아보자.

 

좀 더 다듬어 보자.

 

 

 

쉬어가는 코너

 

 

5. STL

아래의 코드를 참조하자.

 

6. 상속

생성자는 부모 먼저 불리우고, 자식의 생성자가 불리며 소멸자는 반대의 순서이다.

Dog()에서 비록 우리가 아무런 부모생성자 호출 코드를 안 넣었어도 컴파일러가 Dog() : Animal() { ...} 이런 식으로 추가해 준다.  즉 부모 생성자가 먼저 만들어지더다라도, 자식 생성자가 먼저 호출은 된다.

 

protected에 대한 문제

protected 생성자는 자신은 만들 수 없지만, 자식은 만들 수 있게 하는 기술.

 

어떤 관계로 상속 받았냐에 따라서 자식이 물려받은 변수에 영향을 미친다.

 

근데 왜 private을 쓸까? (정말 몰라서 묻는건 아니고, 다음 예제를 보자는 말이다)

 

Vector클래스의 상속권한을 private으로 바꾸자.

 

 

7. Upcasting

자식 클래스는 public으로 상속 받았을 경우, 부모가 요구되는 인자에 자식 클래스로서 갈 수 있다.

좀 더 자세한 Upcating에 대한 소스를 보자.

 

 

 

8. 함수 오버라이딩

 

부모의 함수가 적당하지 않을 때, 같은 이름의 함수로 오버라이드를 할 수 있다.

예를 들어,

Anima* p = &Dog;

라고 있을 때,

p->Cry()

라고 하면,

A:Cry(),

B:Cry()

중 어느 함수를 불러야 할지 결정하게 되는데 이를 바인딩이라고 한다.

 

바인딩(binding)은 다음의 두 종류가 있다.

 static binding(early binding) 

 컴파일러가 컴파일시간에 결정. 원리는 포인터 타입으로 호출

 c++, c#

 dynamic binding(late binding)  컴파일러가 컴파일시 메모리 조사하는 코드를 생성.  실행시 메모리에 어떤 객체가 있는지 조사해서 호출
 java, objective-c, c++(virtual), c#(virtual)

 

관련된 코드는 아래를 참조하자.

 

 

마지막으로 OOP 개념을 살린 예제 코드 한번 보자.(두번 보자)

 

 

   모든 자식에 공통의 전체 알고리즘은 부모가 제공한다.
   하지만 변경되어야 하는 세부 알고리즘은 protected 가상함수로 제공한다.
   전체 알고리즘함수에서 세부 알고리즘 함수를 호출해서 세부알고리즘은 자식이 변경 할 수 있게 하자!

Binder의 Iinterface내에 이 디자인 패턴을 사용했다.

'프로그래밍 > C++' 카테고리의 다른 글

Android Framework 분석을 위한 C++ 4일차  (0) 2012.04.26
[C++] Smart Pointer  (0) 2012.04.25
swap 함수  (0) 2012.04.25
Android Framework 분석을 위한 C++ 2일차  (0) 2012.04.24
Android Framework 분석을 위한 C++ 1일차  (0) 2012.04.23
Posted by code cat