|
음냐리.... 이경문입니다.
보통 virtual 개념이 없을 때 같은 타입의 다른 2개의 객체의 시작포인터와 특정 멤버변수의 위치차이는 같아야 합니다.
흥미로운 현상같아서 3번 vtable에 관해서 델파이를 이용하여 조사를 해 봤습니다.
폼위에 버튼 2개를 올려 놓고 Button1의 Hint만 임의로 변경한후
코드를 다음과 같이 작성하고
Button1 포인터, Button1.Hint 포인터간의 차이와
Button2 포인터, Button2.Hint 포인터간의 차이를 봤습니다.
procedure TForm1.ButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := TButton(Sender);
ShowMessage(Button.Hint);
end;
Button1 : CC2F60
Button1.Hint : CC3330
Button2 : CC33F4
Button2.Hint : 0
Hint이라는 property를 봐도 객체와 멤버간의 차이가 일정치 않다는 것을 알 수 있습니다.
즉, RTTI정보 자체가 virtual(pointer)로 관리되고 있다는 얘기지요.
다시 말해서 DFM을 로딩하여 폼을 생성할 때
일반적으로 Hint property 포인터는 처음에 nil이 되고
DFM중 Hint라는 데이터가 있을 때만 해당객체의 Hint pointer를 수정하게 되고
따라서 vtable이 필요한 것입니다.
어떻게 설명이 되었는지요....
^_____________^
박지훈.임프 님이 쓰신 글 :
: 한 서너달만에 답변을 쓰는군요. ^^;;
:
: __classid는 원래 안시 C++에는 없는 "클래스(타입)에의 포인터"를 돌려주는 키워드입니다.
: C++Builder에서 이런 키워드를 도입한 이유는 오직 오브젝트 파스칼(더 정확히는 VCL)과 상호
: 연동할 수 있게 하기 위해서입니다.
:
: 오브젝트 파스칼에는 클래스에의 포인터라는 타입이 존재합니다.
: TMyComponentClass : class of TMyComponent;
: 이런 식으로 선언했던 것으로 기억합니다.
: (뒤져보기 귀찮아서.. VCL 코드를 뒤져보면 수없이 나옵니다.)
:
: 이것은 C++에는 없는 오브젝트 파스칼만의 특징으로서, '변수'가 아닌 '클래스'에의 포인터입니다.
: 오브젝트 파스칼에서 이런 타입이 존재하는 이유는, 클래스타입을 함수의 인자로 넘겨줘야 할
: 경우가 있기 때문입니다.
:
: 이런 경우는 기본적으로는 컴퍼넌트를 생성할 때나 정적인 폼을 생성할 때처럼 새로운 타입을 동적으로
: 생성할 때 뿐입니다.
: 넘겨받는 함수쪽에서는 해당 타입 자체를 모르므로 해당 타입의 변수를 넘겨받을 수도 없고,
: (함수의 인자 타입들은 코딩시에 다 결정되므로) 그러므로 클래스 타입의 레퍼런스를 넘겨줘서
: 넘겨받은 함수측에서 그것이 가리키는 새 타입을 인식할 수 있도록 하는 것입니다.
:
: 그러므로,
: 1. __classid(TAppLock)가 TMetaClass* TAppLock을 가리키는 것이 맞습니다.
: 2. TMetaClass* TAppLock 대신 __classid를 쓰는 것은 오브젝트 파스칼에서의 문법에 좀 맞춰주려는
: 의도일 뿐입니다. 그냥 TMetaClass* TAppLock라고 쓰셔도 됩니다.
: 3. 저도 확실히는 모르지만, 클래스는 그자체가 타입이지만 내장 타입(primitive)이 아니기 때문에
: vtable에 그 타입에 대한 정보가 저장되는 것이 당연할 겁니다.
:
: __classid는 일반적인 코딩에 쓸 일은 전혀 없습니다.
: 전에 상당히 특이한 방법을 쓰는 델파이 컴퍼넌트를 C++로 옮겼던 적이 있었는데, 저도 거기서 딱
: 한번 쓰고 난 이후로는 전혀 잊고 삽니다.
:
: 그럼...
:
:
: 궁그미 님이 쓰신 글 :
: : 책에 __classid의 역할에 대해
: :
: : C++ Builder's representation of the Object Pascal class-reference type.
: : The TMetaClass for a given class can be acquired by using the __classid operator.
: : The Compiler uses the __classid operator to generate a pointer to the vtable
: : (virtual table) for the given classname.
: :
: : 이렇게 설명되어 있는데요. 예로,
: :
: : RegisterComponentEditor(__classid(TAppLock), __classid(TAppLockEditor));
: :
: : 여기서,
: :
: : 1. __classid(TAppLock)가 TMetaClass* TAppLock라는 뜻인가요?
: : 2. 그렇다면 TMetaClass* TAppLock로 안 쓰고 __class(TAppLock)로 쓰는 이유는 먼가요?
: : 3. vtable를 가리키는 포인터를 생성한다고 했는데요. 저는 virtual function을 가지는
: : 경우 이런 포인터가 생성된다고 알고 있었는데요. __classid 연산과 vtable과 무슨
: : 관계가 있나요?
:
|