C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[133] [팁] C++ Builder와 Delphi의 비교
박지훈.임프 [cbuilder] 20210 읽음    2001-07-30 16:24
이 팁은 담비님(천리안 FREKBS)님이 1999년 04월 07일에 천리안 프로그래머포럼에 올리신 것입니다.
담비님으로부터는 전제하여 올리는 데 대해 허락을 받았습니다.
좋은 정보를 공유하도록 허락해주신 담비님께 감사드립니다.

───────────────────────────────────────

안녕하세요! 담비입니다.

출처 : http://www.inprise.co.jp/tips/cbuilder/cb001/index.html

Borland C++ Builder의 초보적인 프로그래밍에 관하여, Delphi for Windows를 사용한
프로그래밍과의 비교에 관한 설명이다. 처음 C/C++을 사용하여 프로그래밍을 하거나,
Delphi를 사용하였지만 C++ Builder를 사용하여 프로그래밍을 하는것이 알기
어렵다고 생각되는 경우에 참고하기 바란다.

C++ Builder 프로그래밍 정보 - Delphi와의 비교
━━━━━━━━━━━━━━━━━━━━━━━
이 문서는 Borland C++ Builder의 초보적인 프로그래밍에 관하여 Delphi for Windows
를 사용한 프로그래밍과 비교한 것이다.  처음 C/C++을 사용하여 프로그래밍을
하는 경우나, Delphi를 사용하였으나, C++ Builder를 이용한 프로그래밍을 하는것이
알기 어별다고 생각되는 경우 참고하기 바란다. 또한, C++ Builder 사용자 가이드
및 C++ Builder 콤포넌트 개발자 가이드도 함께 읽어주기 바란다.

목차는 다음과 같다.

1. Delphi와 C++ Builder에서의 Data Type 일람
2. string type과 AnsiString Tamplete
3. 집합형과 Set Template
4. OpenArray와 TVarRec Class
5. Variant type과 Variant Class
6. as, is 연산자와 dynamic_cast
7. 예외처리
8. Message 처리
9. 기타

───────────────────────────────────────
1. Delphi와 C++ Builder에서의 Data Type 일람
┏━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━┯━━━━━━┓
┃ Delphi     │size/Value                    │C++에서의 Type  │ 사용 방법  ┃
┠──────┼───────────────┼────────┼──────┨
┃Shortint    │8 비트 정수                   │singed char     │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Smallint    │16 비트 정수                  │short           │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Longint     │32 비트 정수                  │signed long     │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Byte        │8 비트 부호없는 정수          │unsigned char   │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Word        │16 비트 부호없는 정수         │unsigned short  │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃DWord       │32 비트 부호없는 정수         │unsigned long   │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Integer     │32 비트 정수                  │int             │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Cardinal    │32 비트 부호없는 정수         │unsigned int    │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Boolean     │true/false                    │bool            │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃ByteBool    │true/false 또는               │unsigned char   │typedef     ┃
┃            │8 비트 부호없는 정수          │                │            ┃
┠──────┼───────────────┼────────┼──────┨
┃WordBool    │true/false 또는               │unsigned short  │typedef     ┃
┃            │16 비트 부호없는 정수         │                │            ┃
┠──────┼───────────────┼────────┼──────┨
┃LongBool    │true/false 또는               │unsigned int    │typedef     ┃
┃            │32 비트 부호없는 정수         │                │            ┃
┠──────┼───────────────┼────────┼──────┨
┃AnsiChar    │8 비트 부없는 문자            │char            │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃WideChar    │Wide Size의 Unicode 문자      │wchar_t         │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Char        │8 비트 부호 없는 문자         │char            │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃AnsiString  │델파이 AnsiString             │AnsiString      │class       ┃
┠──────┼───────────────┼────────┼──────┨
┃String[n]   │구식 델파이 문자열            │SmallString<n>  │template    ┃
┃            │n-1..255 바이트               │                │class       ┃
┠──────┼───────────────┼────────┼──────┨
┃ShortString │구식 델파이 문자열            │SmallString<255>│typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃String      │델파이 AnsiString 255 바이트  │AnsiString      │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Single      │32 비트 부동 소수점           │float           │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Double      │64 비트 부동 소수점           │double          │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Extended    │80 비트 부동 소수점           │long double     │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Currency    │64 비트 부동 소수점           │Currency        │class       ┃
┃            │소수점 이하 4자리수           │                │            ┃
┠──────┼───────────────┼────────┼──────┨
┃Comp        │64 비트 부동 소수점           │Comp            │class       ┃
┠──────┼───────────────┼────────┼──────┨
┃Set         │1..32 비트                    │Set<type,       │template    ┃
┃            │                              │minval, maxval> │class       ┃
┠──────┼───────────────┼────────┼──────┨
┃Pointer     │32 비트 범용 포인터           │void*           │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃PChar       │문자에 대한 32 비트 포인터    │char*           │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃PAnsiChar   │ANSI 문자에대한 32 비트 포인터│char*           │typedef     ┃
┠──────┼───────────────┼────────┼──────┨
┃Variant     │OLE Variant값 16 바이트       │Variant         │class       ┃
┗━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━┷━━━━━━┛

2. string type과 AnsiString Tamplete
문자열을 표현하는 형으로서 Delphi에서는 string형을 사용하지만,
C++ Builder에서는 AnsiString을 사용한다. AnsiString는 VCL\DSTRING.H에 클래스로
정의되어 있다. AnsiString은 다양한 데이타형에 대응하는 생성자가 준비되어 있어서
다음과 같이 AnsiString형의 데이타를 초기화 할 수 있다.
  AnsiString s1( "String" );     // AnsiString(const char*);가 사용된다.
  AnsiString s2( 'C' );          // AnsiString(const char);가 사용된다.
  AnsiString s3( s1 );           // AnsiString(AnsiString&);가 사용된다.
  AnsiString s4( 128 );          // AnsiString(int);가 사용된다.
  AnsiString s5( 1.5 );          // AnsiString(double);가 사용된다.

또, 이 클래스는 Delphi의 string형과 같이 + 를 사용하여 문자열을 결합하거나 []를
사용하여 지정한 인덱스의 문자를 참조하거나 문자열을 비교할 수 있다. 이것들은
C++의 연산자로 사용되고 있다.
  AnsiString s6( s1 + s2 );
  AnsiString s7( "strings" );
  s5[7] = 's';
  if( s6 < s7 ) ....

AnsiString에는  ==, !=, <, >, <=, >=의 문자열을 비교하기 위한 연산자가 준비되어
있지만, 함수로서 AnsiCompare와 AnsiCompareIc도 준비되어 있다. AnsiCompare는
현재 인스톨되어 있는 언어 드라이버에 의해 문자열을 비교한다. AnsiCompareIC는
대소문자를 구별하지 않고 비교를 한다.

if( s6.AnsiCompereIC( s7 )==0 ) ...

기타, 문자열의 길이를 돌려주는 Length함수, 문자열을 대/소문자로 치환해주는
UpperCase/LowerCase 함수, 공백 문자를 문자열의 선두에서 혹은 마지막에서부터,
양쪽으로부터 없애주는 TrimLeft, TrimRight, Trim 함수 등이 AnsiString 클래스에
함수로 준비되어 있다.

기타, AnsiString으로부터 C/C++에서 사용하는 종래의 데이타형 char*을 꺼내기
위해서는 c_str 함수를 사용한다.

sprintf( buffer, "AnsiString data:%s", s5.c_str() );

VCL\SYSDEFS.H 에서는 typedef AnsiString String으로 정의되어 있으므로 String도
AnsiString과 같은 의미로 사용할 수 있다.

3. 집합형과 Set Template Class
Delphi에서는 순서형의 값을(복수) 저장하는 형으로서 집합이 있다. 집합은 다음과
같이 표현한다.
  Week = (Sun, Mon, Tue, Wed, Thu, Fri, Sat);
  Weeks = set of Week;

예를 들면, Weeks형의 Weekday는 다음과 같이 복수의 값을 저장할 수 있다.

Weekday := [Mon, Tue, Wed, Thu, Fri];

C++ Builder에서는 Delphi의 집합을 Set Template Class를 이용해 표현한다.
Set Template Class는 VCL\SYSDEFS.H에 정의 되어있다. 위의 예를 Set Template
Class를 사용하여 기술은 아래와 같다.
  enum Week {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
  typedef Set  Weeks;

Set Template Class는 집합의 요소를 구성하는 형, 요소의 최소치, 및 요소의
최대치를 사용하여 정의한다.
  Weeks Weekday;
  Weekday << Mon << Tue << Wed << Thu << Fri;

Set 형에 요소를 저장하기 때문에 Set Template Class에는 << 연산자가 준비되어
있다. 연산자 <<는 Set&를 되돌려주는 위의 예와 같이 복수의 요소를 기술할 수있다.
또 같은 연산자 >>은 저장된 요소를 집합으로부터 꺼낸때 사용한다. Set형의 값에
Set형의 값을 대입 논리적, 논리화를 각각 =,*=,+= 연산자로 취할 수 있다. 또 자기
자신을 변경하지 않고 논리적, 논리화를 취한 결과를 돌려주는 연산자 *, + 연산자도
준비되어 있다.
    Weeks W1, W2, W3, W4;
    W1 << Mon << Tue;
    W2 << Tue << Wed;
    W3 = W1 += W2;

Set형에 저장되어 있는 요소가 일치하는가를 비교하는것도 할 수 있다.

if( W3 == (W1+W2) ) ...

Set형에 요소를 저장되어 있는 요소를 확인하기 위해서 Contains함수가 있다.
Contains 함수는 요소를 인수로 가지며, 지정한 요소가 포함되는 경우에는 true를,
포함하고 있지 않는 경우에는 false를 돌려준다.

if( W3.Contains( Mon ) ) ...

이것은 Delphi의 in 연산자에 상당하고 다음과 같이 기술한다.

if Mon in W3 then ...

Set 형에서는 복수의 요소가 포함될지 어떨지를 다음과 같이 확인한다.
  W4 << Mon << Wed;
  if( (W3 * W4) == W4 ) ...

연산자 * 는 논리적인 결과의 Set형의 값을 돌려준다. 또 연산자 ==는 모든 요소가
일치되는지를 확인할 수 있기때문에, W3에 Mon과 Wed가 포함될지를 확인할 수 있다.

Set Class Template의 프로퍼티를 갱신할 때에는 주의가 필요한다. 예를 들면,
TFont::Style 프로퍼티는 TFontStyles 형으로 다음과 같이 정의되어 있다.
  __property TFontStyles Style = {read=GetStyle, write=SetStyle, nodefault};

TFontStyles 형은 다음과 같이 정의되어 있다.
  enum TFontStyle { fsBold, fsItalic, fsUnderline, fsStrikeOut };
  typedef Set  TFontStyles;

TFont::Style 프로퍼티는 값을 취득할 때 GetStyle함수가, 설정할 때에는 SetStyle
함수가 호출되어진다. GetStyle은 TFontStyles의 값을 돌려주며, 그 참조를 돌려주는
것은 아니다. 따라서 다음과 같은 기술은 효력이 없다.

Form1->Font->Style << fsBold;

fsBolde를 추가하려면

Form1->Font->Style = Form1->Font->Style << fsBold;

fsBold를 제거하려면

Form1->Font->Style = TFontStyles() << fsBold;

를 기술한다.

4. OpenArray와 TVarRec Class
Delphi에서는 OpenArray의 파라메타로서 array of const형의 인수를 가지는 함수등이
있지만, C++ Builder에서는 TVarRec* 및 그 파라메타의 수를 대신 사용한다.
TVarRec Class는 저장되어 있는 데이터의 형을 판별하기 위한 VType 및 그 데이타
형에 대응한 각각의 저장 공간이 준비되어 있다. 또, 데이타를 참조하기 위하여
각각의 데이타형에 대응하는 = 연산자가 준비되어 있다.
예를 들면 TDataSet::AppendRecord함수는 Delphi에서는 다음과 같이 정의되어 있다.

procedure AppendRecord(const Values: array of const);

C++ Builder에서는 다음과 같이 TVarRec* 와 그 파라메타의 수를 인수로 가진다.

void __fastcall AppendRecord(const System::TVarRec * Values, const int Values_Size);

예를 들어, Delphi에서의 다음과 같은 코드는

Table1.AppendRecord( [1000] );

C++ Builder에서는,

Table1->AppendRecord( &TVarRec( 1000 ), 0 );

로 표현한다. AppendRecord의 Values_Size 파라메타에는 실제로 건네주는 인수의
수로부터 1 다음의 값을 건네준다. 복수의 파라케타가 있는 경우에는 TVarRec의
배열을 생성해 건네준다. 예를 들면 3개의 필드(Integer형, String형, Float형)을
추가하는 코드는

Table1.AppendRecord( [1, 'string1', 1.0] );

C++ Builder에서는,
  TVarRec flds[] = {1, "string1", 1.0};
  Table1->AppendRecord( flds, 2 );

가 된다. 또 위의 OPENARRAY를 사용해 다음과 같이 한줄로 시술할 수 있다.
  Table1->AppendRecord( OPENARRAY(TVarRec, (1, "string1", 1.0)) );

OPENARRAY는 OpenArray와 OpenArrayCount의 두개의 Class Template를 사용해 처음에
지정한 형의 배열을 생성, 배열의 요소를 지정한 값으로 초기화 한다.
이러한 OpenArray의 인수를 취하는 함수는 다른것도 있다. 댸표적인 것으로는,
Format함수가 거론된다. Format 함수는 지정한 서식지정자라는 인수로부터 문자열을
서식화 한다. Format함수는 다음과 같이 정의되어 있다.
  System::AnsiString __fastcall Format(const System::AnsiString Format,
  const System::TVarRec * Args,
  const int Args_Size);

예를 들면 다음 예는 "Borland C++ Builder 1.0J"라는 값을 돌려준다.
  Format( "%s %s%s %3.1fJ",
  OPENARRAY(TVarRec, ("Borland", "C++", "Builder", 1.0)) );


5. Variant type과 Variant Class
Delphi의 Variant형은, 다른 복수의 형으로서 값을 보존할 수 있는 데이터형으로서
정의되어있지만, C++ Builder에서는 TVarData로부터 파생한 클래스로 사용되어지고
있다. 이 클래스도 각 데이타에 대응하는 생성자를 가지며, 모든 데이타를 저장할
수 있다. 실제로 Variant의 데이타를 사용한 예를 보여준다. Delphi에서는
TDataSet::Locate는 Variant를 인수로 가지기 위해 다음과 같이 정의되어 있다.
  function Locate(const KeyFields: string; const KeyValues: Variant; 
  Options: TLocateOptions): Boolean;

C++ Builder에서는 Variant Class를 사용하기위해 다음의 정의가 되어있다.
  bool __fastcall Locate(const System::AnsiString KeyFields,
  const System::Variant &KeyValues,
  TLocateOptions Options);

Locate를 사용한 간단한 예로는 다음과 같다.
  Table1.Locate('Field1;Field2', VarArrayOf([1, 'string1']), [loPartialKey]);

VarArrayOf는 Variant의 배열로부터 Variant 형 배열의 데이타를 생성한다.
세번째 인수는 TLocateOptions형으로 TLocateOption을 요소에 가지는 집합니다.
위의 코드는 C++ Builder에서 Variant 배열, TLocateOptions Class Template를
사용하여 다음의 기술을 할 수 있다.
  Variant flds[] = {1, "string1"};
  Variant rec( flds, 1 );
  Table1->Locate( "Field1;Field2", rec, TLocateOptions() << loPartialKey );

TLocateOptions() << loPartialKey는 Set Template Class로서 정의된 TLocateOptions
Class를 생성해 TLocateOption의 한개의 요소인 loPartialKey를 세트하고 있다.
  System::Variant __fastcall Lookup(const System::AnsiString KeyFields,
  const System::Variant &KeyValues,
  const System::AnsiString ResultFields);

  Variant v = Table1->Lookup( "Field1;Field2", rec,"Field1;Field2;Field3" );

이 돌아오는 값을 사용해 Variant의 데이타를 어떻게 참조할지를 나타낸다.
Field1은 Integer형, Field2는 String형, Field3은 Float형으로 하면, v로부터
다음과 같이 GetElement 함수를 사용해 각 필드의 데이타를 꺼낼수 있다.
  if( v.IsEmpty() == false ) {
      int Field1 = (int)v.GetElement( 0 );
      AnsiString Field2 = (AnsiString)v.GetElement( 1 );
      float Field3 = (float)v.GetElement( 2 );
  }

GetElement는 Variant Class의 함수로, Variant 배열의 각 요소를 돌려준다.
Variant Class에는 PutElement 멤버함수가 준비되는, 요소와 그 인덱스를 건네주는
것으로 Variant 배열에 데이타를 set할 수 있다.

Variant Class는 OLE Object를 취급할 때도 사용한다. 예를 들면, Delphi에서는
OLE Object의 메소드를 호출할 때 다음과 같이 한다.
  var
  v: Variant;
  begin
     v := CreateOleObject( 'Word.Basic' );
     v.Insert( 'Hello from Delphi' );
     v := Unassigned;
  end;

C++ Builder에서는 Variant는 클래스이므로 위와 같이 직접 메소드를 호출할수는
없다. AutoCmd 클래스로부터 파생된 PropertyGet, PropertySet, Function, Procedure
클래스와 Exec 멤버함수를 하숑하고 OleProcedure, OleFunctin, OlePropertyGet,
OlePropretySet 멤버함수를 사용한다. 또, Variant 클래스에는 CreateOleObject를
호출하는 CreateObject라는 static 멤버함수가 준비되어있다. 처음에 OleProcedure,
OleFunction을 사용해 TEST.DOC를 작성해본다.
  Variant wBasic = Variant::CreateObject( "Word.Basic" );

위의 코드는 Variant::CreateObject의 대신 CreateOleObject로 동일한 동작을 한다.
Word.Basic의 함수 FileNew를 호출한다. Delphi에서는
    wBasic.FileNew( .... );

와 같이 직접 함수명을 사용해 실행하지만, C++ Builder에서는 다음과 같이
OLEFunction을 사용한다.
  wBasic.OleFunction( "FileNew", "표준" );

문자열을 삽입하는 Insert는 절차로서 취급하며, OleProcedure를 사용한다.
  wBasic.OleProcedure( "Insert", "First string\n" );

동일하게 FileSaveAs를 실행해 TEST.DOC를 보존하면, 프로그램은 다음과 같이 된다.
    wBasic = Variant::Createobject( "Word.Basic" );
    wBasic.OleFunction( "FileNew", "표준" );
    wBasic.OleProcedure( "Insert", "First string\n" );
    wBasic.OleFunction( "FileSaveAs", "TEST.DOC" );
    wBasic = Unassigned;

Unassigned를 OLE Object에 대입하여 OLE Object를 파기할 수 있다. 다음에 Exec를
사용해 위의 코드를 다르게 표현한다. Exec는 OLE Object의 메소드와 그 인수 등을
표현하는 AutoCmd와 LOCALEID(디폴트로 LOCALE_SYSTEM_DEFAULT가 할당된다.)를
표현하는 인수로서 건네준다. AutoCmd로부터 파생한 클래스로서 Procedure(절차),
Function(함수), PropertyGet(프로퍼티의 취득), PropretySet(프로퍼티의 설정)이
준비되어 있다. OleFunction의 호출 대신에 Function 클래스를 사용해 호출하는
함수와 그 인수를 설정한다. 생성자에 건네주는 문자열은 메소드명을 표현하며,
그 인수를 << 연사자를 사용해 추가할 수 있다.
  Function func( "FileNew" );
  func << "표준";

실제로 OLE Object의 메소드를 호출할 때에는 Exec에 AutoCmd 클래스의 인스탄스,
이 경우에는 func를 건네주어 호출한다.
  wBasic.Exec( func );

이것들은 다음과 같이 한줄로 기술할 수도 있다.
  wBasic.Exec( Function( "FileNew" ) << "표준" );

Procedure Insert는 Procedure Class를 사용하기때문에, OleFunction을 사용 예로
다음과 같이 바꾸면 된다.
  Variant wBasic = Variant::CreateObject( "Word.Basic" );
  Function func( "FileNew" );
  func << "표준";
  wBasic.Exec( func );
  wBasic.Exec( Proceduer( "Insert " ) << "Frist stirng\n" );
  func.Clear();
  func.SetName( "FileSaveAs" );
  func << "TEST.DOC";
  wBasic.Exec( func );

AutoCmd 클래스에는, OLE Object의 메소드명을 클리어하는 ClearName, 그 인수를
클리어하는 ClearArgs, 어느쪽이나 클리어하는 Clear 메소드가 있으며, SetName에
의해 메소드명을 설정할 수 있다. OleProcedure등의 Variant의 멤버함수는 Exec
멤버함수의 호출로 전개된다.

6. as, is 연산자와 dynamic_cast
Delphi에서는 안전하게 type cast를 하기 위해 as연산자를 사용한다. 예를 들면
다음과 같이 사용한다.
    procedure TForm1.Button1Click(Sender: TObject);
        begin
        try
            (Sender as TButton).Caption := 'Click detected';
        except on E: EInvalidCast do
            Application.ShowException( E );
        end;
    end;

무효한 캐스트를 행하면 EInValidCast 예외가 발생하고, 오브젝트는 부당한 캐스트로
부터 보호된다. C++ Builder에서는 dynamic_cast를 사용해 오브젝트를 안전하게
캐스트할 수 있다. dynamic_cast는 캐스트하는 형 및 오브젝트를 건네준다.
부당한 캐스트가 행해진 경우 dynamic_cast는 실패하고 NULL을 돌려준다. 예를 들면
위의 예를 C++ Builder에서 기술하면 다음과 같이 된다.
     void __fastcall TForm1::Button1Click(TObject* Sender)
    {
        TButton* btn = dynamic_cast(Sender);
        if(btn) btn->Caption = "Click detected";
    }

또, Delphi에서는 오브젝트의 형이 지정된 형에 속하는가를 확인하기 위해
is 연산자를 상요한다. is연산자는 Boolean을 돌려주며 다음과 같이 사용한다.
    procedure TForm1.Button1Click(Sender: TObject);
          begin
          if Sender is TButton then
            TButton(Sender).Caption := 'Click detected';
          end;
    end;

C++ Builder에서는 dynamic_cast를 사용해 결과가 NULL인지를 확인할 수 있기대문에
is연산자에 대해서 dynamic_cast를 사용한다. C++에서는 typeid를 사용해 클래스의
특정을 행할 수 있지만, VCL 클래스는 Delphi의 클래스(__declspec(delphiclass)로서
정의된 클래스)에는 사용할 수 없다.
예를 들면, typeid(*Sender).name()는 "System::TObject"를 돌려준다.
    struct __rtti A
    {
        __fastcall A() {}
        virtual __fastcall ~A() {}
    }
    struct __rtti B: public A
    {
        __fastcall B() {}
        virtual __fastcall ~B() {}
    }
    static const char* getClassName(A* a)
    {
        return typeid(*a).name();
    }
    void foo()
    {
        getClassName(new B);
    }

위의 예의 경우 getClassName는 "B"를 돌려주지만, 클래스 A를 TObject로부터
계승한 클래스로서 선언하면 "A"를 돌려준다.

7. 예외처리
Delphi에서는 예외 처리를 행하는 예약어로서 try, except, finally가 있다.
이것들은 각자, 예외 처리 블럭의 처음, 예외를 핸들링하는 블럭, 예외가 발생되지
않은 경우에도 예외 처리의 뒤처리를 행하는 블럭을 표현하며, 다음과 같이
사용한다.
    try
        try
            : 예외 처리의 기구를 사용해 보호하는 코드
        except
            : 예외가 발생된 때에 실행하는 코드
        end;
    finally
        : 예외가 발생되지 않아도 실행하는 예외 처리의 뒤처리 코드
    end;

C++에서는 except의 대신에 catch를 사용해 예외 핸들러를 작성한다. 또, C++에서는
finally는 정의되어 있지 않다. 따라서 예외가 발생되지 않은 경우에도 실행하려는
코드는 동일한 레벨에 실행되는 것과 같은 위치에 기술할 필요가 있다.
예를 들면 Delphi에서는 except에서 변경된 예외를 보내고 있는 경우에는, 예외를
보내는 앞과, 예외 처리 블럭의 바깥쪽에 기술해야만 한다.
    try {
         : 예외 처리의 기구를 사용해 보호하는 코드
    }
    catch( ... ) {
       : 예외가 발생된 경우에 실행하는 코드
       : 예외 처리의 뒤처리의 코드
    trhow ....
    }
        : 예외 처리의 뒤처리의 코드

catch 블럭에서 예외를 발생되지 않는 경우등(예외 처리 블럭의 이외에 실행 위치를
옮기는 경우)는 예외 처리 블럭의 이외에 두는 것으로 대응할 수 있다.

catch 블럭에서는 예외처리 핸들러를 제한할 수 있다. 예를 들면 다음과 같이
하는것으로 Exception 예외 클래스로부터 파생한 예외만을 받아들인다.
    catch( Exception& e ) {
    }

이것은 Delphi의 except on ... 에 해당한다. catch(...)는 모든 예외를 핸들링할
때 사용한다. 또, TApplication에는 ShowException이라는 멤버함수가 있고, 예외의
내용을 메세지 박스를 사용해 표시한다. 예를 들면 다음 예는 발생한 Exception
예외 내용을 표시한다.
    catch( Exception& e ) {
        Application->ShowException( &e );
    }

기타 C++와 Delphi의 예외 처리 기구에는 주의해야할 차이가 몇가지 있다.
* C++의 파괴자에서는, 완전하게 구축된 멤버와 기본 클래스에 대해 호출한다.
* Object Pascal의 기본 클래스의 파괴자는, 오브젝트 또는 기본 클래스가 완전하게
   구축되어 있지 않은 경우라도 호출한다.
* C++ 예외는, 참조, 포인터, 또는 값에 의해 보충된다.
   TObject로부터 파생한 예외만이 참조 또는 포인터에 의해 보충된다.
   TObject 예외를 값으로 보충하려고 하면 컴파일 에러가 발생한다.
* Object Pascal 예외는 참조에 의해 보충된다.

8. Message 처리
C++ Builder에서는 Windows와 사용자 정의의 메세지를 보충하기 위새서 매크로를
사용한다. 매크로는 BEGIN_MESSAGE_MAP으로 시작되며, MESSAGE_HANDLER 매크로에서
메세지로 호출해지는 함수 및 그 함수로 주어지는 인수의 형을 인수의 형을 정의하고
END_MESSAGE_MAP(XXX)에서 끝난다. END_MESSAGE_MAP의 XXX는 관련한 클래스를 지정
한다. 다음 예는 사용자 정의의 메세지 WM_MYMESSGE를 보충하는 정의이다.
    #define WM_MYMESSAGE (WM_USER + 200)

    class TForm1: public TForm {
    protected:
        void __fastcall WMMyMessage(TMessage& msg);
        BEGIN_MESSAGE_MAP
            MESSAGE_HANDLER(WM_MYMESSAGE, TMessage, WMMyMessage)
        END_MESSAGE_MAP(TForm)
    };

  위의 정의에 의해 WM_MYMESSAGE에 의해 WMMyMessage메소드가 호출되어진다.
  받는 메세지도 사용자가 새로이 정의할 수도 있다. 메세지 구조체는 다음 규칙을
  따른다.
  * 구조체의 이름은, 그 메세지의 이름 선두에 T를 더한다.
  * 처음의 데이타는 Cardinal형으로 메세지의 ID를 식별한다.
  * 다음의 4바이트는 WParam등을 포함하는 메세지이다.
  * 다음의 4바이트는 파라미터에 LParam에 대응하도록 정의한다.
  * 마지막은 Longing형으로 Result에 대응하도록 정의한다.

9. 기타
* Object Pascal에서는 코드중에 사용하는 심볼은 대소분자를 별하지 않지만
   C/C++에서는 구별하기 때문에 C/C++에서는 form1과 Form1은 서로 다른 심볼로
   취급되어진다.

* Delphi에서는 TForm등의 인스탄스는 실제로는 동적으로 생성되어 내부적으로는
   포인터로 취급되지만, 실제로 참조하는 경우에는 C++의 참조와 같이 취급한다.
   C++ Builder에서는 컴포넌트의 인스탄스는 모든 포인터로서 취급한다. 따라서,
   Delphi에서의 From1.Captin은 Form1->Caption으로 참조한다.

* Delphi에서 작성된 클래스(VCL 등)은 인스탄스를 동적으로 생성할 필요가 있다.
   예를 들면 TFont fnt;같은 기술을 허용되지 않는다. 다음과 같이 new 연산자를
   사용해 동적으로 인스탄스를 생성할 필요가 있다.
        TFont *fnt = new TFont;

* Delphi에서는 디폴트 프로퍼티가 있지만 C++ Builder는 그렇지 않다.
   따라서 Delphi에서 ListBox.Items[1]과 같은 기술은 Strings 프로퍼티를
   명시적으로 지정해 참조할 필요가 있다. 다음 예는 각각의 리스트 박스에 등록된
   처음의 문자열, 메모 컴포넌트에 써진 두줄째의 문자열, 팝업 메뉴의 세번째에
   등록된 메뉴의 문자열을 캡션에 대입하고 있다.
        Caption = ListBox1->Items->Strings[0];
        Caption = Memo1->Lines->Strings[1];
        Caption = PopupMenu->Items->Items[2]->Caption;

* 파스칼에서는 다차원 배열을 xxx[x,y]와 같이 표현하지만, C/C++ 에서는 xxx[x][y]
   와 같이 표현한다. 따라서 그리드 컴퍼넌트의 Cells 프로퍼티는 Cells[x][y]로
   참조한다.

+ -

관련 글 리스트
133 [팁] C++ Builder와 Delphi의 비교 박지훈.임프 20210 2001/07/30
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.