본문 바로가기

전체 글115

Doxygen Quick Guide - Doxygen 주석 > *Doxygen 기본 스타일 /** */ *주석안에 아이템들 @breif ==> 설명을 쓴다. 여러줄을 쓸때에는 @breif를 쓰고 한줄 띄운다움 계속해서 쓰면된다. @file ==> 파일 이름을 구별할때. @return ==> 함수의 리턴값 나타낼때. @author ==> 작성자 이름을 나타낼때 @date ==> 작성날짜를 나타낼때. @param ==> 함수 파라메터를 나타낼때 @see ==> 참고할 함수나 페이지를 지정한다. @todo ==> 다음에 작업해야 될 내용 @bug ==> 버그에 대한 기술 @code ==>중요 코드를 설명할때 시작 지점 가리킨다. @endcode ==> 중요코드 설명할때 종료 지점 가리킨다. @exeception ==> @mainpage ==> Doxygen 메인 페이.. 2008. 8. 5.
항목 8. 예외가 소멸자를 떠나지 못하도록 붙들여 놓자. class DBConnection { public: static DBConnection create(); void close();}; 위의 DBConnection 객체에 대해 사용자가 cloase를 직접 호출해야 하는 설계이다. 사용자의 망각을 사전에 차단하는 좋은 방법이라면 DBConnection에 대한 자원관리 클래스를 만들어서 그 클래스의 소멸자에서 close를 호출하게 만드는 것이다. class DBConn { // DBConnection 객체를 관리하는 클래스 public: ... ~DBConn() // 데이터베이스 연결이 항상 닫히도록 확실히 챙겨주는 함수 { db.cloase(); } private: DBConnection db; }; 위의 두 클래스를 활용하여 다음과 같은 프로그래밍이 가능.. 2008. 7. 10.
단일체 (Singleton) 코드 #include template class Singleton { static T* ms_Singleton; public: Singleton( void ) { assert( !ms_Singleton ); int offset = (int)(T*)1 - (int)(Singleton *)(T*)1; ms_Singleton = (T*)((int)this + offset); } ~Singleton( void ) { assert( ms_Singleton); ms_Singleton = 0; } static T& GetSingleton( void ) { assert( ms_Singleton ); return ( *ms_Singleton ); } static T* GetSingletonPtr( void ) { return.. 2008. 7. 5.
항목 7. 다형성을가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자. C++의 규정에 의하면, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때 그 기본 클래스에 비가상 소멸자가 들어 있으면 플그램 동작은 미정의 사항이라 되어 있다. 대게 그 객체의 파생 클래스 부분이 소멸되지 않게 된다. 가상 소멸자를 선언하는 것은 그 클래스에 가상 함수가 하나라도 들어 있는 경우에만 한정하자. (이부분은 뭐라 정리하기 힘들다 이해는 했는데 내용 정리가 힘들다 추후 다시 정리 예정) 이것만은 잊지 말자! - 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 한다. 즉, 어떤 크랠스가 가상 함수를 하나라도 갖고 있으면, 이 클래스의 소멸자도 가상 소멸자이어야 한다. - 기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않는 클래스에는 가상 소멸자를 선언하지 말아야.. 2008. 7. 1.
2008.06.27 작업 내역 - 클라이언트 리비전 1 to 2 //--------------------------------------------------------------------- // 클라이언트 리비전 #2 // 오후 12:35:00 2008.06.27 (금) //--------------------------------------------------------------------- // 작업 내역 1. 기존의 D3D_Api.Cpp 의 함수들을 CDxApi 클래스로 묶었다. 2. CGameMng 클래스를 추가 하였다. 3. CMediator 부모 클래스를 생성 하였다. // 파일 변화 내역 Delete D3D_Api.cpp Delete D3D_Api.h Add DxApi.cpp Add DxApi.h Add GameMng.cpp Add GameMng... 2008. 6. 27.
항목 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자. 하나밖에 없는 클래스 즉, 똑같은게 없는 클래스를 만든다고 할 때 객체는 사본(copy)를 만드는 것 자체가 이치에 맞지 않다. 그러다 보니 객체를 복사하려 하는 코드는 컴파일이 되지 않게 하려면 어떻게 해야 할까? HomeForSale h1; HomeForSale h2; HomeForSale h3(h1); // h1을 복사하려 한다. - 컴파일이 되면 안된다. h1 = h2; // h2를 복사 하려 한다. - 컴파일이 되면 안된다. 해결 방법 - 컴파일러가 생성하는 복사 생성자와 복사 대입 연산자는 public 으로 자동 생성 해버리므로 이들을 private 멤버로 선언 하면 된다. ㄴ 효과1 : 클래스 멤버 함수가 명시적으로 선언되어 컴파일러는 자시느이 기본 버전을 만들 수 없다. ㄴ 효과2 : 비공.. 2008. 6. 27.
항목 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 복사 생성자, 복사 대입 연산자, 생성자, 소멸자 는 사용자가 선언을 하지 않아도 컴파일러가 자동으로 public inline 함수로 선언해 버린다. calss Empty{}; class Empty { public: Empty() { ... } // 기본 생성자 Empty(const Empty& rhs) { ... } // 복사 생성자 ~Empty() { ... } // 소멸자 Empty& operator= (const Empty& rhs) { ... } // 복사 대입 연산자 위의 두 클래스는 같다고 보면 된다. 참조 1. 복사 생성자를 제외한 생성자를 선언하면 컴파일러가 기본 생성자는 만들지 않는다. 이것만은 잊지 말자! - 컴파일러는 경우에 따라 클래스에 대해 기본 생성자, 복사 생성자, 복사 대입.. 2008. 6. 27.
ReleaseDC 위치가 중요한가? 스프라이트 툴 제작 중 ZoomDlg 에서 이상하게 메모리 누수가 발생 하였다.. 대충 소스는 다음과 같이 작성을 하였었다.. { CClientDC dc(this); CDC* pDC = CWnd::GetDC(); ... // dc를 얻어와 Dialog 창에 뿌리는 작업 들.. ... ... ... ... ... ... ... dc.StretchBlt(0, 0, drt.right, drt.bottom, pDC, spt.x, spt.y, sWidth, sHeight, SRCCOPY); dc.MoveTo(drt.right/2, drt.top); dc.LineTo(drt.right/2, drt.bottom); dc.MoveTo(drt.left, drt.bottom/2); dc.LineTo(drt.right, d.. 2008. 6. 20.
항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자. 초기화되지 않은 값을 읽도록 내버려 두면 정의되지 않은 동작이 그대로 흘러 나오게 된다. 모든 객체를 사용하기 전에 항상 초기화 하자! 기본제공 타입으로 만들어진 비멤버 객체에 대해서는 초기화를 손수 해야 한다. int x = 0; // int의 직접 초기화 const char* text = "A C-style string"; // 포인터의 직접 초기화 double d; // 입력 스트림에서 읽음으로써 std::cin >> d; // "초기화" 수행 이런 부분을 제외하고 나면, C++의 초기화의 나머지 부분은 생성자로 귀결된다. 생성자에서 지킬 규칙은 간단하다. 그 객체의 모든 것을 초기화하자! 단 대입(assignment)을 초기화(initialization)와 헷갈리지 말자! class PhoneNu.. 2008. 6. 10.
항목 3. 낌새만 보이면 const를 들이대 보자! const 사용처 클래스 바깥에서는 전역 혹은 네임스페이스 유효범위의 상수를 선언(정의)하는 데 쓸 수 있다. 파일, 함수, 블록 유효범위에서 static으로 선언한 객체에도 const를 붙일 수 있다. 클래스 내부의 경우 정적 멤버 및 비정적 데이터 멤버 모두를 상수로 선언할 수 있다. char greeting[] = "Hello"; char *p = greeting; // 비상수 포인터, 비상수 데이터 const char *p = greeting; // 비상수 포인터, 상수 데이터 char * const p = greeting; // 상수 포인터, 비상수 데이터 const char * const p = greeting; // 상수 포인터, 상수 데이터 void f1(const Widget *pw); .. 2008. 6. 10.
항목 2. #define을 쓰려거든 const, enum, inline을 떠올리자. 이유 1. 컴파일러는 선행 처리자를 밀어버리고 숫자 상수로 바꾸어 버리기 때문이다. #define ASPECT_RATIO 1.653 위와 같이 코드를 썻다고 하면 ASPECT_RATIO 라는이름은 컴파일러가 쓰는 기호 테이블레 들어가지 않는다. 그래서 숫자 상수로 대체된 코드에서 컴파일 에러라도 발생하게 되면 골치가 아플 수 있다. 소스 코드엔 분명히 ASPECT_RATIO가 있었는데 에러 메시지엔 1.653이 있으니 말이다. 해결책 1. 매크로 대신 상수를 사용하자. const double AspectRatio = 1.653; AspectRatio는 언어 차원에서 지원하는 상수 타입의 데이터이기 때문에 당연히 컴파일러의 눈에도 보이며 기호 테이블에도 당연히 들어간다. 게다가 상수가 부동소수점 실수 타입.. 2008. 5. 29.
const 키워드의 의미 const 키워드의 용도는 변수를 상수화 시키기 위해 사용 한다. - const int n = 10; n 은 변수이나 const 키워드를 붙여줌으로 상수화 되었다. 따라서 n에 다른 값을 대입하는 것은 허용되지 않는다. - const int* n; 데이터 상수화. n이라는 포인터가 가르키는 값을 상수화 시킨다. - int* const n; 포인터 상수화. n이 가르키는 포인터를 상수화 시킨다. - const int* const n; 데이터와 포인터 상수화. 2008. 5. 28.