18. Design Interface

소프트웨어를 설계할 때,
인터페이스를 설계하고, 이후 이를 선언하여 사용한다.

인터페이스 사용자가 인터페이스 생성자가 생각한대로 사용하지 않는다면,
컴파일되지 않도록 해야 한다.

설계할 때, 미리 사용자가 잘못 쓸수 있는 부분을 제한해야 한다.
1. 타입 시스템(wrapper type)
class Date{
public:
Date(int month, int day, int year);
// ...
};
위와 같이 인터페이스를 생성하게 되면, 잘못된 값이 대입되어도 실수를 막을 수 없다.
타입 시스템(새로운 타입을 정의하여 사용)을 이용할 수 있다.
struct Day{
explicit Day(int d): val(d) {}
int val;
};
struct Month{
explicit Month(int m): val(m) {}
int val;
};
struct Year{
explicit Year(int y): val(y) {}
int val;
};
class Date{
public:
Date(const Month& m, const Day& d, const Year& y);
// ...
};
위와 같이 타입을 명시해줄 경우, 인자의 순서를 검사할 수 있다.
Date d(Month(3), Day(30), Year(1995));
Month는 유효한 값이 12개 밖에 없어 enum이나 집합을 미리 정의하고 이용할 수 있다.
(단, enum은 타입 안정성이 떨어짐)
class Month{
public:
static Month Jan(){ return Month(1); }
static Month Feb(){ return Month(2); }
// ...
static Month Dec(){ return Month(12); }
// ...
private:
explicit Month(int m);
// ...
};
static으로 선언하지 않으면 비정적 객체로 초기화 순서가 정해지지 않는다.
2. const
if(a*b=c);
만일 위에서 a*b==c를 실행할려고 했는데 실수로 =을 하나만 사용하였을 경우,
에러가 없이 동작할 수 있다.
만일 operator* 연산자가 const를 반환한다면, 위와 같은 에러를 막을 수 있다.
(a*b에 애초에 값을 대입하는 표현식은 있을 수 없기 때문에 const를 사용해도 상관없다.)
3. 교차 DLL 문제(cross-DLL problem)
객체 생성시에 사용한 동적 링크 라이브러리(Dynamically Linked Library: DLL)의 new와
다른 DLL의 delete를 사용한 경우 발생하는 문제이다.
보통 런타임 에러가 발생한다.

std::shared_ptr은 생성된 DLL과 동일한 DLL에서 delete를 사용함을 보장한다.
std::shared_ptr<Investment> createInvestment(void){
return std::shared_ptr<Investment>(new Stock); // Stock Investment
}
shared_ptr은 객체의 참조 카운터가 0이되어 소멸될 때까지 내부적으로
어떤 DLL의 delete를 사용해야 하는지 저장하고 있다.

실제로 shared_ptr은 일반 포인터의 두 배의 크기를 가지며,
내부에 내부관리 데이터 및 삭제자 메커니즘을 돌리기 위해 동적 할당 메모리를 사용하며,
다중스레드로 돌아가는 프로그램에서는 스레드 동기화도 지원한다.