[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" 어떤 문제를 해결하기 위한 설계를 찾을 때 가상 함수를 대신하는 방법들도 고려해보자! "
- 가상 함수 대신에 쓸 수 있는 다른 방법으로 NVI 관용구 및 전략 패턴을 들 수 있으며 이 중 NVI 관용구는 그 자체가 템플릿 메서드 패턴의 한 예이다!
- 객체에 필요한 기능을 멤버 함수로부터 클래스 외부의 비멤버 함수로 옮기면, 그 비멤버 함수는 그 클래스의 public 멤버가 아닌 것들을 접근할 수 없다는 단점이 생긴다!
- tr1::function 객체는 일반화된 함수 포인터처럼 동작한다. 이 객체는 주어진 대상 시그니처와 호환되는 모든 함수호출성 개체를 지원한다.
class GameCharacter
{
public:
int healthValue() const
{
...
int retVal = doHealthValue();
...
return retVal;
}
...
private:
virtual int doHealthValue() const;
{
...
}
}:
비가상 인터페이스 관용구(NVI)를 사용
- 공개되지 않은 가상 함수를 비가상 public 멤버 함수로 감싸서 호출하는 템플릿 메서드 패턴의 한 형태
어쨌든 가상 함수를 사용하기에 눈속임과 같다...
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter
{
public:
typedef int (*HealthCalcFunc) (const GameCharacter&);
explicit GameCharacter(HealthCalFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{ return healthFunc(*this); }
...
private:
HealthCalFunc healthFunc;
};
가상 함수를 함수 포인터 데이터 멤버로 대체
- 전략(sttrategy)패턴의 단순한 응용
같은 타입으로 만들어진 객체들도 체력치 계산 함수를 다르게 가릴 수 있다
class EvilBadGuy : public GameCharacter
{
public:
explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc)
: GameCharacter(hcf)
{ ... }
};
int loseHealthQuickly(loseHealthQuickly);
int loseHealthSlowly(loseHealthSlowly);
class GameCharacter
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter
{
public:
typedef function<int (const GameCharacter&)> HealthCalcFunc;
explicit GameCharacter(HealthCalcFunc hcf = defalutHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{ return healthFunc(*this); }
...
private:
HealthCalcFunc healthFunc;
}:
class GameCharacter
class HealthCalcFunc
{
public:
...
virtual int calc(const GameCharacter& gc) const
{ ... }
...
}:
HealthCalcFunc defaultHealthCalc;
class GameCharacter
{
public:
explicit GameCharacter(HealthCalcFunc* phcf = &defaultHealthCalc)
: pHealthCalc(phcf)
{}
int HealthValue() const
{ return pHealthCalc->calc(*this); }
...
private:
HealthCalcFunc* pHealthCalc;
};