[ Programming ]2009. 6. 23. 17:10
핵심은 C++가 인터페이스와 구현을 깔끔하게 분리하는 일. 
어떻게 정의 됐는지 모르면 컴파일 자체가 불가능. 
정의 된 정보를 가져 오려면 #include를 써서 가져와야 함. #include "Date.h" #include "Address.h" 이렇게 #include를 사용하면, 컴파일 의존성이 생겨 버린다. 즉, Date와 Address를 변경하면, 변경하지 않은, CPerson도 컴파일 하게 됨. 

- 객체 참조자 및 포인터로 충분한 경우에는 객체를 직접 쓰지 않는다. 
- 할 수 있으면 클래스 정의 대신 클래스 선언에 최대한 의존. 
- 선언부와 정의부에 대해 별로의 헤더 파일을 제공.
pimpl 관용구("pointer to implementation")
 
PersonImpl.h
#ifndef _PERSONIMPL_H_
#define _PERSONIMPL_H_

#include < iostream >

class CDate
{

};

class CAddress
{

};

class CPersonImpl	/// 구현 부분.
{
public:
	CPersonImpl(const std::string& name, const CDate& birthday, const CAddress& address)
		: theName(name), theBirthDay(birthday), theAddress(address)
	{

	}
	std::string GetName() const
	{
		return theName;
	}
	CDate		GetBirthday() const
	{
		return theBirthDay;
	}
	CAddress	GetAddress() const
	{
		return theAddress;
	}
private:
	std::string	theName;
	CDate		theBirthDay;
	CAddress	theAddress;
};

#endif

Person.h
#ifndef _PERSON_H_
#define _PERSON_H_

#include < string >
#include < boost/tr1/memory.hpp >

/// 인터페이스 구현에 필요한 전방 선언들.
class CDate;
class CAddress;
class CPersonImpl;

class CPerson		/// 인터페이스 부분.
{
public:
	CPerson(const std::string& name, const CDate& birthday, const CAddress& address);
	~CPerson();
	std::string Name() const;
	CDate BirthDay() const;
	CAddress Address() const;
private:
	/// 구현 부분에 대한 포인터.
	std::tr1::shared_ptr< CpersonImpl > m_pPersonImpl;
};

#endif

Person.cpp
#include "Person.h"
#include "PersonImpl.h"

CPerson::CPerson(const std::string &name, const CDate &birthday, const CAddress &address)
: m_pPersonImpl(new CPersonImpl(name, birthday, address))
{

}
CPerson::~CPerson()
{

}

std::string CPerson::Name() const
{
	return m_pPersonImpl->GetName();
}

CDate CPerson::BirthDay() const
{
	return m_pPersonImpl->GetBirthday();
}

CAddress CPerson::Address() const
{
	return m_pPersonImpl->GetAddress();
}

멤버 함수를 호출하면 구현부 객체의 데이터까지 가기 위해 포인터를 타야 함. 
즉 한번 접근 할 때 마다 요구 되는 간접화 연산이 한 단계 더 증가. 
객체 하나씩을 저장하는 데 필요한 메모리 크기에 구현부 포인터의 크기가 더 해짐. 
구현부 포인터가 동적 할당된 구현부 객체를 가리키도록 어디선가 그 구현부 포인터의 초기화가 일어나야 함. 

위와 같은 단점도 있지만, 컴파일의 의존도를 최대한 줄여서 컴파일 시간을 줄여 시간을 절약 할수 있음.
Posted by 냉동