|
아~~
0 님 감사합니다.
몰랐던것 몇 배우네요
첫째로
:멤버 함수로 호출 될 때는 클래스의 인스턴스 포인터를 스택에 저장해두고 해당 함수로 넘어가고
:해당 함수 내에서 그 것을 꺼내서 this 포인터로 사용합니다.
==> 이것 새롭게 처음알게된 사실입니다.
님이 쓰신대로 함수형을
typedef void __fastcall ( *TObjectEvent2)(void *, System::TObject* Sender);
뭐 위와같은 형태로 하니까 this가 Form이 되네요
Form의 멤버인 Edit나 기타 등에도 access되구
typedef void __fastcall ( *TObjectEvent)(System::TObject* Sender);
위와같은 형태로 호출하면서 Sender에 Form이아니라 다른것을 주면
해당함수에서 Form의 멤버를 참조하려고 할경우 문제가 되네요
둘째로
:컴파일 링크 과정에서 함수는 이름으로 저장되지 않고 주소로 바뀌어 저장되는데 Published는 이름도 함께 저장되는
:모양입니다.
==> 어렴풋 그렇지 않을까 생각하고 있었는데....
그러니까 컴파일된 exe에 Published로 된 멤버함수나 변수는 저장이 그 이름을 기억한단 말이죠?
그럼 Published는 다형성이 안되겠네요 .. ㅎㅎ
테스트로 아래와 같이 하니까 Link에러가 나는군요
__published:
void __fastcall PublicMethod(TObject *Sender);
void __fastcall PublicMethod(TObject *Sender, int k);
Form위에 Design을 *.dfm처럼 파일을 만들어서
run-time때 load해서 연결하고 싶은데...
다른것은 다 될것 같은데 Method연결이 잘안되겠네요
일일이 Form의 모든 published 함수에 대해 string으로 비교하는 구분을 만들지 않구
뭐 좋은 방법 없을까요?
하여간 다시한번 감사합니다.
그럼...
0 님이 쓰신 글 :
: 장성호 님이 쓰신 글 :
: : MethodAddress 함수 써보신분 계신가요?
: :
: : TObject의 MethodAddress 메소드는 반환값이 void* 입니다.
: : VCL에 객체멤버함수의 포인터인 8Byte가 아니라
: : win32시스템에 기본형인 4Byte짜리 void * 인것입니다.
: :
: : void *로 받아서 형변환해서 함수 호출하면
: : 객체 내부에서 호출되는것이 아니라 이상하게 호출됩니다.
: :
: : 아래코드에서 Button2Click 과 Button3Click 을 하면 어떻게 나타날가요?
: :
: : Button2Click 하면 "Form2"가 ShowMessage되고
: : Button3Click 하면 "Button3"가 ShowMessage됩니다. 이런 황당한...
: :
: : 단지 호출할때 Sender를 Form2와 Button3로 다르게 넘겨준것인데...
: :
: : 왜그런거죠?
: : 1. 왜 Button1Click 함수내에서 Sender가 this가 되버린거죠?
: : 2. 왜 MethodAddress 는 Published만 찾을수 있는거죠? ( 그렇게 만들어 놓았기때문이라는 답변 말구요)
: : String으로 객체멤버함수를 찾을수는 없는건가요? 그렇다면 왜 그런지요?
: :
: : 누가 MethodAddress에 대해 좀 자세히 가르쳐 주세요
: :
: : FieldAddress 도 같은 원리인것 같은데 같이 설명좀...
: :
: :
: : [MethodAddress 사용예]
: :
: : void __fastcall TForm2::Button1Click(TObject *Sender)
: : {
: : ShowMessage(this->Caption);
: : }
: : //---------------------------------------------------------------------------
: : typedef void __fastcall ( *TObjectEvent)(System::TObject* Sender);
: : void __fastcall TForm2::Button2Click(TObject *Sender)
: : {
: : TObjectEvent BtnClick;
: : void *tt=MethodAddress(this->ClassType(), "Button1Click"); //or MethodAddress( "Button1Click");
: : BtnClick=(TObjectEvent)tt;
: : if(BtnClick)BtnClick(this);
: : }
: : //---------------------------------------------------------------------------
: : void __fastcall TForm2::Button3Click(TObject *Sender)
: : {
: : TObjectEvent BtnClick;
: : void *tt=MethodAddress(this->ClassType(), "Button1Click");// or MethodAddress( "Button1Click");
: : BtnClick=(TObjectEvent)tt;
: :
: : if(BtnClick)BtnClick(Sender);
: : }
: : //---------------------------------------------------------------------------
: :
: : 미리 감사드립니다.
:
: BtnClick는 TForm2의 멤버 함수로 호출된 게 아니고 비 멤버 함수로 호출되었습니다.
: 멤버 함수로 호출 될 때는 클래스의 인스턴스 포인터를 스택에 저장해두고 해당 함수로 넘어가고
: 해당 함수 내에서 그 것을 꺼내서 this 포인터로 사용합니다.
: BtnClick의 경우는 멤버 함수로 호출되지 않았으므로 클래스의 인스턴스 포인터가 스택에 들어가 있지 않은 상태에서 호출되게 되고 해당 함수 내부에 진입되었을 때 스택에서 꺼내게 되는 this 포인터는 엉뚱한 값이 됩니다.
: (지금의 경우 함수의 첫번째 매개변수가 this 포인터로 오인됩니다)
: 따라서, 아래와 같이 우회할 수도 있으나 표준은 아니며 함수호출규약에 따라 작동하지 않을 수도 있습니다.
: typedef void __fastcall ( *TObjectEvent)(TForm2*, System::TObject* Sender);
: if(BtnClick)BtnClick(this,this);
: if(BtnClick)BtnClick(this,Sender);
:
: 아래와 같은 형변환이 허락된다면 좋겠지만 허락되지 않는군요.
: typedef void __fastcall (TForm2::*Method)(System::TObject* Sender);
: Method m1 = (Method)MethodAddress(this->ClassType(), "Button1Click");
: if(m1) (this->*m1)(Sender);
:
: MethodAddress는 컴파일 시간이 아닌 실행 시간에 메서드 이름으로 그 주소를 구하는 것이므로
: Published만 가능하다면 실행시간에는 Published 외에는 이름 정보가 없는 것으로 보입니다.
: 컴파일 링크 과정에서 함수는 이름으로 저장되지 않고 주소로 바뀌어 저장되는데 Published는 이름도 함께 저장되는 모양입니다.
|