긴 말보다 몇줄의 코드가 좋을 것 같다.
간단한 인터페이스와 구현 클래스를 예로 들어보겠다.

class IAbc // 단순한 인터페이스 클래스
{
public:
 virtual void Print() = 0; // 단순한 인터페이스 하나 선언
};

class CAbc : public IAbc
{
IAbc* m_pNext;
public:
 CAbc() {cout << "CAbc Constructor" << endl;} // 생성자가 불리는지 확인
 ~CAbc() {cout << "CAbc Destructor" << endl;} // 소멸자가 불리는지 확인
 void Print() {cout << "CAbc" << endl;} // IAbc의 인터페이스 구현
};

이와 같이 설계를 했다면 아래 코드와 같이 사용할 것이다.
(편의상 생성 패턴은 생략한다.)

IAbc *pAbc;
pAbc = new CAbc;
pAbc->Print();
delete pAbc;

첫줄은 변수 선언이므로 아무 변화 없다.
두번째 줄에서 CAbc의 객체를 실제 만들었으므로 CAbc의 객체가 생성되며, 따라서 CAbc의 생성자가 호출된다.
세번째 줄에서 pAbc는 IAbc의 변수이나 virtual로 선언된 멤버 함수를 호출하기 때문에, 실제 객체인 CAbc에서 구현한 Print가 호출된다.
네번째 줄이 문제이다. pAbc의 실제 객체가 CAbc란 정보가 없기 때문에 pAbc는 C++ 컴파일러 내부에서 자동으로 생성한 기본 소멸자인 ~IAbc()만 호출하고 종료한다. 만약 CAbc의 소멸자에서 메모리 해제 등의 일을 구현한 경우 이것은 무시된다. 따라서 인터페이스 클래스의 경우에도 기본 생성자, 소멸자는 반드시 정의하여야 한다.

올바른 IAbc의 코드는 아래와 같다.

class IAbc // 단순한 인터페이스 클래스
{
public:
 IAbc() {};
 virtual ~IAbc() {};
 virtual void Print() = 0; // 단순한 인터페이스 하나 선언
};

생성자의 경우는, 무엇을 만들지를 정한 후에 객체를 생성하므로 당연히 필요한 생성자가 불리게 된다. 그러나 소멸자의 경우는 어느 포인터를 사용하여 소멸자를 호출할 지 알 수 없으므로 위와 같이 가상함수로 소멸자를 정의하여야 한다. 물론 ~IAbc의 가상함수를 정의했다고 하여, CAbc에서도 ~IAbc()를 오버라이드할 필요는 없다. CAbc에서는 ~CAbc()를 구현하면 알아서 IAbc의 소멸자가 호출되는 경우 CAbc의 소멸자가 불리게 된다.

Posted by raychani / 레이찬
다이얼로그 내에 픽처 컨트롤이나, ANIMATE 컨트롤을 넣어, 이 안에서 동영상을 재생하는 경우, 재생이 시작해도 윈도우 내에 화면 갱신이 일어나지 않는다.
이때 컨트롤의
m_cScreen.ModifyStyle(0, WS_CLIPCHILDREN);
를 호출하면 재생시 화면 갱신이 정상적으로 일어난다. 다만 WM_PAINT 이벤트를 처리하기 위해서는 다른 방법이 필요한 듯 하다.
Posted by raychani / 레이찬
VC++ 6.0 MFC AppWizard (exe) 프로젝트에서 _MBCS대신 UNICODE를 정의하면 빌드시에 아래와 같은 링크에러가 발생한다.
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
Project Setting의 Link->Output->Entry-point symbol에 wWinMainCRTStartup을 입력하면 정상적으로 빌드된다.
Posted by raychani / 레이찬

지식 분류는?

지식 2007/08/11 21:54
내 생각이 아닌 객관적인 사실을 적기 위한 분류이다.
그 중에서도 특히 나에게 도움이 될 글들을 적을 것이다.
C++, DirectShow, STL, COM등의 하위 분류를 생각하고 있다.
Posted by raychani / 레이찬