본문 바로가기

Programming62

항목 7. 다형성을가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자. C++의 규정에 의하면, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때 그 기본 클래스에 비가상 소멸자가 들어 있으면 플그램 동작은 미정의 사항이라 되어 있다. 대게 그 객체의 파생 클래스 부분이 소멸되지 않게 된다. 가상 소멸자를 선언하는 것은 그 클래스에 가상 함수가 하나라도 들어 있는 경우에만 한정하자. (이부분은 뭐라 정리하기 힘들다 이해는 했는데 내용 정리가 힘들다 추후 다시 정리 예정) 이것만은 잊지 말자! - 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 한다. 즉, 어떤 크랠스가 가상 함수를 하나라도 갖고 있으면, 이 클래스의 소멸자도 가상 소멸자이어야 한다. - 기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않는 클래스에는 가상 소멸자를 선언하지 말아야.. 2008. 7. 1.
항목 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.