//------------------------------
// 선언부
class CA
{
public:

	void Func();
};

class CB : public CA
{
public:

	using CA:Func;
	void Func( int a );
}

//-----------------------------
// 구현부

CB* pTestClass = new CB;

pTestClass->Func();
pTestClass->Func( 1 );

using CA:Func; 를 선언하지 않을 경우
pTestClass->Func(); 는 영영 사용 불가능 ㅋ.. 형변환을 해서 써야한다.
아니 그전에 함수가 없다고( 인자를 받는 함수 뿐이라고 ) 에러를 뱉어낸다.

윈도우 기반 문자열 출력은 내부에서 자체적으로 유니코드로 컨버팅을 해줘 문제가 없지만,
printf등 콘솔 명령어를 쓴다면 한글이 제대로 나오지 않는다.
한글로만 테스트를 했지만 유니코드 자체가 출력이 제대로 안되는 걸로 봐서 2바이트 문자는 전부 무리가 가는듯?

String strBuf;
strBuf.Format( "%s", strText );

printf( "%s", strBuf );

이런 코드가 있다고 하면 제대로 출력이 되지 않는다.

해결방법!

프로그램 시작하는 곳 제일 처음에 아래 한줄을 추가.
그러면 문제가 깔끔하게 해결된다.

std::locale::global( std::locale( "kor" ) );

추가하고 출력을 해보자.
제대로 나오지는 않을것이다.
printf문에서 파라메터를 %s에서 %S로 수정.

이걸로 완료.

모든것을 테스트 해보지는 않았지만 구글신이 알려주신거니 믿고 따르자. ㅎ

구조체* m_pArrStruct[MAX_COUNT_1][MAX_COUNT_2]; 라 선언되어 있는 녀석. 즉, 3차원 배열에 대한 자그마한 삽질.
( 어떠한 클래스의 멤버 변수. )

c/c++ 에서는 2차원 배열 이상은 포인터 리턴 같은 기능이 없다.( 라고 합니다.. 잘은 모르지만 다들 그렇다닌까 그런가하고 있음. )

다른 클래스에서 저 데이터를 받아오기 위해선 인자( parameter )로 받아오는 수 밖에 없다.

void get( 구조채*** pppParam )
{
*pppParam = &m_pArrStruct[0][0];         // 리턴의 기준은 2차 배열의 시작 주소.
}


구조체** ppStruct;
Class.get( &ppStruct );

ppStruct[0][0] == m_pArrStruct[0][0][0];
ppStruct[1][0] == m_pArrStruct[0][1][0];
ppStruct[2][5] == m_pArrStruct[0][2][5];

기준은 2차 배열의 주소이긴 하나, 위에서 1차 배열를 고정시켜버렸기 때문에 m_pArrStruct[1]의 주소는 나오기 힘들다.

혼자 삽질 한것이기 때문에, 태클은 자제하겠습니다~.

웹서핑 조금만 해도 나오는 싱글턴 패턴 소스.
평소처럼 사용하다가 싱글턴 클래스 상속과 싱글턴을 상속받은 부모 클래스를 다시 자식 클래스가
상속을 받아서 쓰는부분에 대해 궁금함이 생겼다.

일반적인 싱글턴 소스들
template< class T >
class CLmSingleton
{
public:
	static T	*getInstance() {
		if( !s_pInstance ) s_pInstance = new T();
		return s_pInstance;
	}
	static void	releaseInstance() {
		if( s_pInstance ) { delete s_pInstance; s_pInstance = NULL; }
	}

protected:
	static T *s_pInstance;
};

template< class T > T *CLmSingleton< T >::s_pInstance = 0;

//-------------------------------------------------------------- template< class T > class CLmSingleton2 : private T { public: static T* getInstance() { // if use in multi-thread env, should add lock here. static CLmSingleton2<t> s_Instance; return& s_Instance; } protected: CLmSingleton2() {} virtual ~CLmSingleton2() {} }; #define SINGLETON(p) CLmSingleton2<p>::getInstance()

상단에 있는 싱글턴 소스는
class A : public CLmSingleton<A>
{
public:
	A() {}
	virtual ~A() {}

	int a;
};

A testClass;			// 일반적인 정적 변수 선언이 가능.
testClass.a = 99;		// 이것은 단순히 testClass 라는 클래스 멤버변수의 값만 바뀐다.
A* pA0 = testClass.getInstance(); // pA0의 멤버변수 a의 값은 쓰레기 값
A* pA1 = A::getInstance();
A* pA2 = CLmSingleton<A>::getInstance();
// pA0, pA1, pA2 세 포인터의 주소는 동일하다.
pA2->a = 98;			// pA0, pA1, pA2의 멤버변수 a가 전부 갱신됨.

testClass 와 포인터들은 다른 주소를 갖는다. 다만 testClass.getInstance() 로 불러오는 인스턴스만은 동일하다.
각각의 인스턴스는 동일하지만 ( testClass != 포인터 ) 이기 때문에 싱글턴이라 부르기 어렵다.
또한, 싱글턴의 특징 중 하나인 외부로 공개하지 않는 생성자와 소멸자가 public이다.
결국, 저 클래스는 실수로라도 정적 변수로 선언을 하게 된다면 나중에 문제가 커질 가능성이 있다.

혹시나 해서 생성자와 소멸자를 protected 와 private로 했는데, 생성자에 접근을 하지 못해 컴파일 에러가 뜬다.


두번째 테스트로 상속을 받지 않고 싱글턴을 적용해 보았다.
class B
{
public:
	B() {}
	virtual ~B() {}

	int b;
};

B* pb0 = B::getInstance(); // 상속을 받지 않았으므로 B에는 getInstance()란 메소드가 없어 오류
B* pb1 = CLmSingleton<B>::getInstance(); // B 클래스라는 새로운 인스턴스 생성 성공.


마지막 테스트는 상단 소스중 CLmSingleton2 로 했다.
class C
{
public:			// protected 도 가능
	C() {}
	virtual ~C() {}

	int c;
};

class C : public CLmSingleton2<C> 로 선언 자체가 안된다. 소스를 보면 서로가 서로를 상속 받는 구조가 되어버린다.

두번째 싱글턴의 경우, 그 특징은 사용하려 명시한 클래스의 자식클래스로 상속이 된다. 첫번째는 싱글턴 자체가 부모클래스이고 사용하고 싶은 클래스는 자식클래스로 상속을 시키는 구조다.

이 싱글턴은 단지 아래 방법만이 가능하다.
C* pc0 = SINGLETON(C);
C* pc1 = SINGLETON(C);

두번째 싱글턴의 경우 클래스 생성자가 public이든 protected든 인스턴스가 생성이 된다. protected인데 생성이 되는 이유는 싱글턴이 부모의 생성/소멸자를 상속을 받았기에 내부에서는 부모를 참조할 수 있기 때문이다. private의 경우 생성/소멸자를 상속 시키지 않아 컴파일 에러가 난다.

//----------
그리고 두 싱글턴의 차이를 보자면 첫번재는 동적 인스턴스이다. 가져올때 없으면 new로 할당을 하고 존재한다면 이미 만들어진 인스턴스를 가져온다. 하지만 소멸자는 불리지 않아 인스턴스가 제대로 지워졌는지 확인이 안된다.
아니면 releaseInstance()를 호출하는 수 밖에 없다.

하지만 두번째 싱글턴은 정적 인스턴스이기 때문에 클래스 자체가 파괴가 되거나 프로그램이 종료가 된다면 메모리를 반환을 한다. 메모리 해제를 할 필요가 없다는 것이다.
그리고 첫번째 싱글턴처럼 인스턴스를 생성할 때 여러 방법이 불가능하다. 싱글턴 생성이나 인스턴스를 가져옴에 있어 통일성이 있다.
만약, 첫번째 싱글턴처럼 이렇게 만드나 저렇게 만드나 똑같은 인스턴스가 나온다면 인스턴스를 가져올 때 통일적이지 않아 나중가면 햇갈릴 가능성이 있는 것이다.

개인적으로 두번째 싱글턴이 좋다.

'잡동사니' 카테고리의 다른 글

장난칠때 써먹을 반한 잡지식?  (0) 2009.10.29
성향 테스트  (0) 2009.10.05
UNICODE <-> UTF8  (0) 2009.08.17

이 프로그램은 Sleep( 2000 )을 걸고! 퍼포먼스 카운터와 어셈블리 카운터와 타임겟타임을 비교해본것임.

순서대로 curTime 은 Performance Counter로 계산한 Elapsed time 이라고 할까요? 단위는 ns
part pc 는 ms단위의 Performance Counter,
curRe 는 앞에는 Performance Counter, 뒤에는 Assembly count 인데, 바로 전 상황과 현재의 차이.
asm pc 는 Assembly counter,
tgt.. timeGetTime
마지막 pc 는 순수한 Performance Counter의 값.

curRe 에서 보이듯이 어셈으로 테스트 했을땐 sleep( 2000 )에 맞게 딱딱 떨어졌는데,
퍼포먼스 카운트는 정확하게 2000으로 떨어지지가 않는다.( 요기도 역시 ns 단위 )

중간에 한번 변위가 엉망인 이유는 듀얼 코어.. 크흑.

확실히 퍼포먼스 카운터가 정밀도가 높아서 2초 단위로 찍어도 ns에서 나온 결과를 보면 수치가 조금씩 다르다.
멋쟁이 정밀도. 대신에 그 만큼 느리다는 단점은 널리 알려진 것이고.
근데.. 온라인 게임에서 쓰기에 ns단위까지 갈 필요가 있을까 라고 개인적으로 생각해본다.
그래서 개인적으로 timeGetTime을 주로 쓰는데 가끔 테스트로 GetTickCount 역시 사용하고. ㅋ
하지만 정밀도는 조금 버리는 한이 있더라도 역시 게임은 반응이 빨라야 재밌지. 함수 호출하는 시간을 조금이라도 더 아껴서
빠른 반응을 보인다면 약간의 딜레이정도는 무난하지 않을까 싶다. 그런의미에서 이제는 어셈 카운터가 원츄~!

참고로. performance counter 와 assembly counter 는 __int64형 timeGetTime은 DWORD형.
참고2. 어셈카운터는 ns 에서 0이 하나 더 붙어있는 값으로 나오더라 ㅋㅋ