동적 생성 지원 클래스 만들기

Development/C / C++ 2006. 11. 20. 16:45
//RTTI(run time type information) example
#include
#include



#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)



class CObject;

//{{struct CRuntimeClass------------------------------------------------
struct CRuntimeClass {
char m_lpszClassName[21];
int m_nObjectSize;
CObject* (*pfnCreateObject)();

CObject* CreateObject();
};//struct CRunTimeClass

CObject* CRuntimeClass::CreateObject() {
return (*pfnCreateObject)();//함수 포인터를 이용하여
//간접적으로 함수를 호출한다.
}//CRuntimeClass::CreateObject()
//}}struct CRuntimeClass------------------------------------------------

//{{class CObject-------------------------------------------------------
class CObject {
//CObject는 순수 가상함수를 포함하지 않으므로
//추상 클래스가 아니다. 하지만, 생성자가 protected로 설정되었으므로,
//CObject객체를 생성할 수 없다.
public:
virtual CRuntimeClass* GetRuntimeClass() const { return NULL; }
//파생 클래스에서 반드시 구현할 필요가 없으므로
//순수가상함수가 아니다.
static CRuntimeClass classCObject;
//DECLARE_DYNAMIC(CObject)
virtual ~CObject(){}
protected:
CObject(){ printf("CObject constructor\n"); }
};//class CObject

CRuntimeClass CObject::classCObject={//IMPLEMENT_DYNAMIC(CObject)
"CObject",sizeof(CObject),NULL
};
//}}class CObject-------------------------------------------------------

//{{class CAlpha--------------------------------------------------------
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCAlpha;
}
static CRuntimeClass classCAlpha;
//DECLARE_DYNAMIC(CAlpha)
static CObject* CreateObject();
//DECLARE_DYNCREATE(CAlpha)
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};//class CAlpha

CRuntimeClass CAlpha::classCAlpha = {//IMPLEMENT_DYNAMIC(CAlpha)
"CAlpha", sizeof(CAlpha), CAlpha::CreateObject
};

CObject* CAlpha::CreateObject() {//IMPLEMENT_DYNCREATE(CAlpha)
return new CAlpha;
}
//}}class CAlpha--------------------------------------------------------

//{{class CBeta---------------------------------------------------------
class CBeta : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCBeta;
}
static CRuntimeClass classCBeta;
//DECLARE_DYNAMIC(CBeta)
static CObject* CreateObject();
//DECLARE_DYNCREATE(CBeta)
protected:
CBeta() { printf("CBeta constructor\n"); }
};//class CBeta

CRuntimeClass CBeta::classCBeta = {//IMPLEMENT_DYNAMIC(CBeta)
"CBeta", sizeof(CBeta), CBeta::CreateObject
};

CObject* CBeta::CreateObject() {//IMPLEMENT_DYNCREATE(CBeta)
return new CBeta;
}
//}}class CBeta---------------------------------------------------------

void main() {
//Create CAlpha
CRuntimeClass* pRTCAlpha=RUNTIME_CLASS(CAlpha);
CObject* pObj1;

pObj1=pRTCAlpha->CreateObject();
//struct RuntimeClass의 CreateObject()가 호출되지만
//IMPLEMENT_DYNCREATE 매크로에 의해 CAlpha의 &CreateObject()가
//대입되어 있으므로, 결국은 CAlpha의 CreateObject()가 호출되어
//동적으로 객체를 생성하게 된다.
//문제를 푸는 열쇠는 바로 '함수 포인터'이다.
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);

//Create CBeta
CRuntimeClass* pRTCBeta=RUNTIME_CLASS(CBeta);
CObject* pObj2;

pObj2=pRTCBeta->CreateObject();
printf("CBeta class=%s\n", pObj2->GetRuntimeClass()->m_lpszClassName);
//일관된 방법으로 클래스를 만들고 해제하는 것에 주목하라.

delete pObj1;
delete pObj2;
}//main





// 매크로를 사용한 소스



//RTTI(run time type information) example
#include
#include



//{{RTTI macros---------------------------------------------------------
#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)



#define DECLARE_DYNAMIC(class_name) static\
CRuntimeClass class##class_name;



#define IMPLEMENT_DYNAMIC(class_name) CRuntimeClass\
class_name::class##class_name = {\
(#class_name),\
sizeof(class_name),\
class_name::CreateObject };



#define DECLARE_DYNCREATE(class_name) static CObject* CreateObject();



#define IMPLEMENT_DYNCREATE(class_name) CObject*\
class_name::CreateObject() {\
return new class_name; }
//}}RTTI macros---------------------------------------------------------

class CObject;//forward declaration of CObject

//{{struct CRuntimeClass------------------------------------------------
struct CRuntimeClass {
char m_lpszClassName[21];
int m_nObjectSize;
CObject* (*pfnCreateObject)();

CObject* CreateObject();
};//struct CRunTimeClass

CObject* CRuntimeClass::CreateObject() {
return (*pfnCreateObject)();//함수 포인터를 이용하여
//간접적으로 함수를 호출한다.
}//CRuntimeClass::CreateObject()
//}}struct CRuntimeClass------------------------------------------------

//{{class CObject-------------------------------------------------------
class CObject {
//CObject는 순수 가상함수를 포함하지 않으므로
//추상 클래스가 아니다. 하지만, 생성자가 protected로 설정되었으므로,
//CObject객체를 생성할 수 없다.
public:
virtual CRuntimeClass* GetRuntimeClass() const { return NULL; }
//파생 클래스에서 반드시 구현할 필요가 없으므로
//순수가상함수가 아니다.
DECLARE_DYNAMIC(CObject)
//static CRuntimeClass classCObject;
virtual ~CObject(){}
protected:
CObject(){ printf("CObject constructor\n"); }
};//class CObject

CRuntimeClass CObject::classCObject={
"CObject",sizeof(CObject),NULL
};
//}}class CObject-------------------------------------------------------

//{{class CAlpha--------------------------------------------------------
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCAlpha;
}
DECLARE_DYNAMIC(CAlpha)
//static CRuntimeClass classCAlpha;
DECLARE_DYNCREATE(CAlpha)
//static CObject* CreateObject();
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};//class CAlpha

IMPLEMENT_DYNAMIC(CAlpha)
//CRuntimeClass CAlpha::classCAlpha = {
// "CAlpha", sizeof(CAlpha), CAlpha::CreateObject
//};

IMPLEMENT_DYNCREATE(CAlpha)
//CObject* CAlpha::CreateObject() {
// return new CAlpha;
//}
//}}class CAlpha--------------------------------------------------------

//{{class CBeta---------------------------------------------------------
class CBeta : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const {
return &classCBeta;
}
DECLARE_DYNAMIC(CBeta)
//static CRuntimeClass classCBeta;
DECLARE_DYNCREATE(CBeta)
//static CObject* CreateObject();
protected:
CBeta() { printf("CBeta constructor\n"); }
};//class CBeta

IMPLEMENT_DYNAMIC(CBeta)
//CRuntimeClass CBeta::classCBeta = {
// "CBeta", sizeof(CBeta), CBeta::CreateObject
//};

IMPLEMENT_DYNCREATE(CBeta)
//CObject* CBeta::CreateObject() {
// return new CBeta;
//}
//}}class CBeta---------------------------------------------------------

void main() {
//Create CAlpha
CRuntimeClass* pRTCAlpha=RUNTIME_CLASS(CAlpha);
CObject* pObj1;

pObj1=pRTCAlpha->CreateObject();
//struct RuntimeClass의 CreateObject()가 호출되지만
//IMPLEMENT_DYNCREATE 매크로에 의해 CAlpha의 &OnCreate()가
//대입되어 있으므로, 결국은 CAlpha의 OnCreate()가 호출되어
//동적으로 객체를 생성하게 된다.
//문제를 푸는 열쇠는 바로 '함수 포인터'이다.
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);

//Create CBeta
CRuntimeClass* pRTCBeta=RUNTIME_CLASS(CBeta);
CObject* pObj2;

pObj2=pRTCBeta->CreateObject();
printf("CBeta class=%s\n", pObj2->GetRuntimeClass()->m_lpszClassName);
//일관된 방법으로 클래스를 만들고 해제하는 것에 주목하라.

delete pObj1;//delete pRTCAlpha는 왜 (논리적) 에러인가?
delete pObj2;
}//main

:

#pragma once

Development/C / C++ 2006. 11. 15. 14:14

출처 : http://blog.naver.com/topgunmagic

#pragma once

C의 헤더 파일 최상단에서 자주 볼 수 있는 이 코드는 컴파일러에게 이 헤더 파일이 한번만 빌드되도록 알려주는 명령입니다.

왜 넣어야 하냐면, A.h라는 파일이 여러 곳에서 복잡하게 #include 되어 쓰이게 된다면 그때마다 각각 정의가 추가되게 되어 중첩되는 경우가 발생됩니다. 이 경우 중복 정의되었다는 에러가 발생하게 되지요. 즉 같은 내용이 여러번 빌드되게 되는겁니다. 이를 막기위해 #pragma once가 필요합니다. 물론 컴파일시간도 줄여주므로 대부분의 헤더파일에 추가하기를 추천합니다.

#pragma는 C언어에서 컴파일러에 직접 정보를 전하기 위해 사용합니다.

MSDN에서 발췌한 내용입니다.

#pragma once

Specifies that the file will be included (opened) only once by the compiler in a build. This can reduce build times as the compiler will not open and read the file after the first #include of the module.

For example,

// header.h 
#pragma once ....

=================================================================

1.define시에 꼭 정의를 할 필요는 없다.

#define A

#ifdef _A
....(코드)
#endif
라고 사용하는데
컴파일러가 컴파일할때 위 문장을 만나면 _A 가 이전에 정의되어있는지 확인합니다.
#define _A 라는 문장이 이전에 나왔는지 검사한다는 이야기입니다.

확인후 정의되어 있으면 #ifdef 부터 #endif 까지 컴파일을 하죠.
하지만 정의되어있지 않으면 #ifdef 부터 #endif 까지 해석하지않고 건너뜁니다.
마치 /* ... */ 주석으로 막아둔 부분처럼 말입니다.

4)
#ifndef _DEFINES_H_
#define _DEFINES_H_
처럼 만드는 부분은 일반적으로 헤더를 만들때 헤더를 define 문으로 묶어주는데
헤더 마지막에 #endif 가 있을 겁니다.
이렇게 해놓으면
정의된 헤더는 한번만 해석되죠. 컴파일될때 한번만 된다는 말입니다.
처음 #include "헤더" 했을때는 _DEFINES_H_ 란 이름이 한번도 정의도지 않았습니다.
그러니까 소스에 한번 들어갑니다.
들어가니까 _DEFINES_H_ 를 한번 정의해주는군요.
만약 다음에도 똑같이 #include 로 헤더를 집어넣어도 _DEFINES_H_ 가 한번 정의되어
있기때문에 인클루드되지않습니다.
그렇기때문에 중복정의되었다는 오류를 내보내지 않죠.

컴파일시 안전을위해 정의해둔 일종의 보험이죠.

5) 추가내용
#ifndef 는 if not defined 란 말로 정의가 되어있지 않으면~이란 말입니다.

#ifdef 이름 는 #if defined(이름) 과 같은 말이고
#ifndef 이름 은 #if !defined(이름) 과 같은 말입니다.

다음과 같이 사용할 수도 있습니다.

#ifdef ...
<정의되었을경우>
#else
<정의되지 않았을경우>
#endif

#if defined(하나) && defined(둘)
#endif

#if defined(하나) && defined(둘) || defined(셋) ...
#endif

#ifdef 하나
#elif defined(둘)
#elif defined(셋) && !defined(넷)
#else
#endif

마음데로 사용하실수 있습니다.

18-3.pragma 지시자

18-3-가.once

C 언어의 장점 중 하나는 어느 운영체제나 플랫폼으로 쉽게 이식될 수 있는 이식성(Portability)이다. 유닉스에서 작성한 소스를 윈도우즈로 가져와 컴파일하면 똑같은 동작을 하는 실행 파일을 얻을 수 있다. 그러나 이 이식성은 어디까지나 소스 차원에서 이식 가능성을 의미하는 것이지 컴파일된 결과인 실행 파일은 그렇지 않다. C언어는 이식성이 있지만 C언어를 특정 플랫폼에 맞게 컴파일하여 고유의 실행 파일을 만들어 내는 컴파일러는 본질적으로 플랫폼에 종속적이다.

그래서 각 플랫폼에서 실행되는 컴파일러는 플랫폼의 고유한 기능을 수행하기 위한 지원을 해야 한다. 플랫폼별로 구조나 기능이 다르기 때문에 구현도 약간씩 달라질 수 있는데 예를 들어 메모리를 관리하는 방식이나 실행 파일의 특수한 구조로 인한 코드 배치 방법이 플랫폼별로 고유하다. #pragma 지시자는 플랫폼별로 다른 이런 기능에 대한 지시 사항을 컴파일러에게 전달하는 방법이다. #문자로 시작하므로 전처리 명령처럼 보이지만 컴파일러 지시자이다. #pragma 지시자의 기본 형식은 다음과 같다.

#pragma 토큰문자열

#pragma 다음에 지시 사항을 전달하는 토큰 문자열이 오는데 이 토큰의 종류는 컴파일러별로 다르다. 플랫폼에 종속적인 기능에 대한 지시자이므로 #pragma 지시자는 컴파일러에 대해서 종속적일 수밖에 없다. 그래서 특정 플랫폼을 위한 프로그램을 작성할 때만 사용해야 하며 꼭 이식성을 유지하려면 조건부 컴파일 지시자와 함께 사용해야 한다. 컴파일러는 #pragma 다음의 토큰을 인식할 수 없을 경우 단순히 무시해 버리며 컴파일은 계속 수행한다. 다음은 비주얼 C++ 6.0의 pragma 토큰들이다.

alloc_text, auto_inline, bss_seg, check_stack, code_seg, comment, component, conform

const_seg, data_seg, deprecated, function, hdrstop, include_alias, init_seg, inline_depth

inline_recursion, intrinsic, managed, message, once, optimize, pack, pointers_to_members

pop_macro, push_macro, runtime_checks, section, setlocale, unmanaged, vtordisp, warning

종류가 굉장히 많고 이 중 몇 가지는 굉장히 어렵고 복잡한 것도 있다. 우선 가장 이해하기 쉬운 once부터 구경해 보자. 이 지시자를 헤더 파일 선두에 써 두면 컴파일러는 딱 한 번만 헤더 파일을 포함하여 컴파일 시간을 절약한다. 다음과 같은 조건부 컴파일 지시자로 한 번만 포함되도록 하는 것과 효과가 동일하다.

#ifndef _SOME_HEADER_FILE

#define _SOME_HEADER_FILE

// 헤더 파일 내용

#endif // _SOME_HEADER_FILE

같은 헤더 파일을 일부러 두 번 포함하지는 않겠지만 헤더 파일끼리 서로 중첩을 하다 보면 원치 않게 두 번 포함되는 경우도 있다. 헤더 파일에 중복해도 상관없는 선언만 있다면 아무 문제가 없겠지만 중복해서는 안되는 정의가 있는 경우는 이런 식으로 한 번만 포함하도록 해야 한다.

:

November Rain

ETC. 2006. 11. 15. 09:11
November Rain

When I look into your eyes. I can see a love restrained.
But darlin when I hold you, don't you know I feel the same.
Cause nothin lasts forever,
and we both know hearts can change.
And it's hard to hold a candle, in the cold November rain.
We've been through this such a long long time,
just tryin to kill the pain.
But lovers always come and lovers always go
An no one's reallly sure who's lettin go today.
Walking away.
If we could take the time to lay it on the line.
I could rest my head,
just knowin that you were mine, all mine.
So if you want to love me, then darlin don't refrain.
Or I'll just end up walkin, in the cold November rain.
Do you need some time on your own.
Do you need some time all alone.
Everybody needs some time on their own.
Don't you know you need some time all alone.
I know it's hard to keep an open heart.
When even friends seem out to harm you.
But if you could heal a broken heart.
Wouldn't time be out to charm you.
Sometime I need some time on my own.
Sometime I need some time all alone.
Everybody needs some time on their own.
Don't you know you need some time all alone.
And when your fears subside, and shadows still remain.
I know that you can love me,
when there's no one left to blame.
So never mind the darkness, we still can find a way.
Cause nothin lasts forever, even cold November rain.
Don't ya think that you need somebody.
Don't ya think that you need someone.
Everybody needs somebody.
You're not the only one.

:

The Death Clock

ETC. 2006. 10. 31. 12:56
http://www.deathclock.com
죽을 날을 알려주는 사이트!!!

생년월일/성별/성향/체중지수/흡연여부 등을 입력받아 계산해주는 사이트이다.
뭐 어차피 이게 정확하겠냐만은...

일단 한번 해보시라니까요~~ ㅎ

주의 : BMI수치는 하단에 계산해주는 것이 있음.

2006년 10월 31일 PM12:57분 현재 나의 남은 시간은... ㄷㄷㄷ

Your Personal Day of Death is...
Tuesday, May 2, 2056
Seconds left to live...
1,562,115,991
:

JavaScript와 JScript의 차이점

News & Tips 2006. 10. 30. 16:42

출처 : http://blog.naver.com/sj99yang.do?Redirect=Log&logNo=140003739792

JavaScript에 대한 오해는 끝이 없이 없다. 혹자는 Java Language와 JavaScript를
혼동하기도 한다.

ECMA(European Computer Manufacturers Association)에서 논의되던 표준 중에
ECMA-262라는 것이 있다. ECMA-262는 Script에 대한 표준이며 이것은 ECMAScript라고
불리기도 한다.

Netscape社는 ECMAScript를 나름대로 구현하였다. 이것이 JavaScript이다. 2004년
1월 현재 버전 1.5까지 나와 있다.

한편, Microsoft社도 ECMAScript에 대한 구현물을 내놓았는데 이것이 JScript이다.
JScript의 버전 5.6까지 확인하였으며 Internet Explorer와 Windows OS의 변화에
따라서 계속 버전이 올라가는 중이다.

Internet Explorer의 HTML Script Tag에 Language 속성을 'JavaScript'로 주어도
여전히 JScript를 사용하게 된다. 결국 IE는 사용자가 JavaScript Reference를 보고
프로그램을 작성하였다 할지라도 기어이 JScript로 구동한다는 것이다. 따라서
IE에서 표현되는 HTML Page를 작성할 때에는 반드시 MSDN에 있는
JScript Reference를 참고해야한다. Netscape社 홈페이지 어딘가에 있는 JavaScript
Reference를 참고할 경우 프로그램이 원하는 데로 동작하지 않을 수 있다.

현재 JScript나 JavaScript는 ECMA-262에서 정의한 것보다 더 많은 기능을 지원한다.
예를 들자면 try catch statement도 그 중 하나이다. Microsoft社와 Netscape社는
ECMA-262를 처음 구현한 뒤로 계속 기능을 추가시켜왔고, 그에 따라 두 Script는
기능상 상이점이 점점 많아지게 되었다. 이점 때문에 두 Script를 구분하여
사용하는 것은 중요하다 할 수 있다.

Microsoft의 JScript나 VBScript는 COM(Component Object Model) Object와 원활히
통신할 수 있어, HTML Page를 꾸미는 것 이외에도 다양한 용도로 사용된다.

========================================================================
헉... 몰랐다 -_-;;;

: