//\"저기 말이죠., 미스터 프레지던트... 그루지야놈들이 도발해서, 버르장머리 좀 고쳐주려고 우리가 침공했소. 이해해주쇼.\"
지난 번에는 상속 문제 때문에 Singleton<Foo>::GetInstance()... 꼴로 쓰자고 했잖아.
근데 관념적으로는 저게 좀 어색한 코드거든. Singleton의 인스턴스를 가져오는 모양 같아.
게다가 원래는 Foo::GetInstance()꼴로 써왔기도 하고 해서, 고민을 좀 해봤는데,
단일체 함수자 템플릿이라고는 대충 이름을 지었는데,
파생 클래스가 기초 클래스와 같은 이름의 멤버 변수를 갖고 있을 때,
기초 클래스의 것을 가려버리는 특성을 이용한 거야.
//FunctorSingleton
template <class T>
class FunctorSingleton
{
public:
T* operator()(void)
{
if(mThis)
return mThis;
else
return mThis = new T;
}
protected:
static T* mThis;
};
template <class T> T* FunctorSingleton<T>::mThis = 0;
class FunctorSingleton
{
public:
T* operator()(void)
{
if(mThis)
return mThis;
else
return mThis = new T;
}
protected:
static T* mThis;
};
template <class T> T* FunctorSingleton<T>::mThis = 0;
class Foo
{
public:
virtual void RetrieveSelf()
{
std::cout << \"Foo\" << std::endl;
}
public:
static FunctorSingleton<Foo> GetInstance;
};
FunctorSingleton<Foo> Foo::GetInstance;
class Bar : public Foo
{
public:
virtual void RetrieveSelf()
{
std::cout << \"Bar\" << std::endl;
}
public:
static FunctorSingleton<Bar> GetInstance;
};
FunctorSingleton<Bar> Bar::GetInstance;
int main(void)
{
Foo::GetInstance()->RetrieveSelf();
Bar::GetInstance()->RetrieveSelf();
}
{
public:
virtual void RetrieveSelf()
{
std::cout << \"Foo\" << std::endl;
}
public:
static FunctorSingleton<Foo> GetInstance;
};
FunctorSingleton<Foo> Foo::GetInstance;
class Bar : public Foo
{
public:
virtual void RetrieveSelf()
{
std::cout << \"Bar\" << std::endl;
}
public:
static FunctorSingleton<Bar> GetInstance;
};
FunctorSingleton<Bar> Bar::GetInstance;
int main(void)
{
Foo::GetInstance()->RetrieveSelf();
Bar::GetInstance()->RetrieveSelf();
}
Foo
Bar
나름 그럴 듯한 것 같아서 한 번 올려봤음..
오 왠지 그럴싸하다?
ㄴ그렇긴 한데, 그렇다고 해서 문제될 건 없다고 봐. 어차피 FunctorSingleton 클래스도 갖고있는 건 포인터뿐이니깐...
operator() 함수가 실행될 때에 인스턴스가 생성되거나, 가져오니깐 딱히 문제는 없다고 봐. 그게 문제라면 단일체 템플릿 패턴 자체의 결함인 거고...
만약에 FunctorSingleton이 static T* mThis가 아니라, static T mThis라면 문제가 되겠지만, 단순히 포인터니깐...;
파생 클래스를 만든다고해서 똑같은 걸 하나 더 만드는 건 아니니깐. 게다가 실제로 단일체인 클래스를 상속받아서 새로운 클래스를 만들어야 할 경우도 꽤 있어
Bar 이전에 Foo가 생성되어야 하는 건 맞는데, 어쨌든 Bar하고 Foo는 뿌리는 같지만 엄연한 다른 클래스지.
음, 근데 그 관점도 조금 맹점이 있는 게, 만약 Foo의 자식으로 클래스 본문에 GetInstance 외에 아무것도 없는 (그러니까 부모하고 완전히 동일한) 클래스를 하나 만들어버린다면?
ㄴ음? 잘 이해가 안가..; 좀 만 더 자세히...
http://codepad.org/dl8KmEQb
ㄴ이게 왜? 정상 작동하는 것 같은데
저건 너무 당연한 거지. C++의 특성을 개무시한 건데 어떡해..;
근데 상속 문제는 다른 데에서도 충분히 거론되고 있는 문제들이기도 한데, 단일체인 클래스의 생성자에는 멤버 변수 초기화 이외엔 거의 다른 짓을 안하거든
그래서 나는 단일체를 상속을 받는 게 달리 문제될 건 없다고 보는 입장이야. 물론 내부 구현에 따라 독이 될 수도 있기는 하지만.
아, 말실수..; 단일체인 클래스의 생성자에는 멤버 변수 초기화 이외엔 거의 다른 짓을 안한다는 건 어디까지나 내가 그렇게 한다는 얘기..;
나 같은 경우에는 그냥 Initialize 뭐 이런 함수를 따로 만들어놓기 때문에...
아 좋은 해결책이 떠올랐다...
음 그럴듯한데?