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

C++빌더 Q&A
C++Builder Programming Q&A
[52101] Re:Re:폼 생성자 오버로드 문제에 대해 문의드립니다.
장성호 [nasilso] 2080 읽음    2008-01-29 00:37
네... 방태윤님말씀대로 하면 됩니다.

그런데 그 원인은 ....

TCustomForm에 있습니다.
public:
    __fastcall virtual TCustomForm(Classes::TComponent* AOwner);
    __fastcall virtual TCustomForm(Classes::TComponent* AOwner, int Dummy);


TCustomForm에 생성자에 위와같이 두가지 형태로 이미 존재합니다.

그런데 TCustomForm의 소스를 보면

constructor TCustomForm.Create(AOwner: TComponent);   //생성자1
begin
  GlobalNameSpace.BeginWrite;
  try
    CreateNew(AOwner);                                                      //생성자2
    if (ClassType <> TForm) and not (csDesigning in ComponentState) then
    begin
      Include(FFormState, fsCreating);
      try
        if not InitInheritedComponent(Self, TForm) then
          raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
      finally
        Exclude(FFormState, fsCreating);
      end;
      if OldCreateOrder then DoCreate;
    end;
  finally
    GlobalNameSpace.EndWrite;
  end;
end;


생성자1에서 생성자2를 호출합니다.
그런데
Form2의 오버라이드 한 생성자 형태가 CustomForm의 두번째 생성자와 형태가 똑같고
또한 Form2의 두번째생성자에서 Form의 첫번째 형태의 생성자를 호출하고있으니...
TCustomForm에서는 의 생성자에서는 두번째형태의 생성자를 다시 호출하고...
그러면 Virtual로 된 함수이니 실제함수이 TForm2의 두번째형태의 생성자를 호출하고...
그것이 무한 반복되어 stack over flow가 나는것입니다.



해결

방법1.
    생성자를 오버라이드 할때   TComponent  * Owner ,  Int  ... 형의 생성자를 쓰지 않고
    다른 형태로 바꿔쓴다..
  

방법2.
   TForm2(TComponent* Owner, int inputValue); 형태로 쓸때
   실제함수에서 TForm의 생성자를 호출할때도 두번째 형태의 함수를 호출한다.

__fastcall TForm2::TForm2(TComponent* Owner,int val)
    : TForm(Owner,val)       /// TForm(Owner)  ==> TForm(Owner,val)   이런 형태로 호출하면...
{
    ShowMessage("adfasdf");
}

   그런데 이렇게 하면 폼의 모양이 이상하게 나옵니다.
   왜 그런가하면....
   위 TCustomForm의 두번째 생성자인 CreateNew
   C++Builder에서는 (TComponent* Owner,int val) 형태의 생성자는
   폼을 생성할때  리소스 파일을 참조하여 폼위에 올려진 Component를 생성해주지 않습니다.

    다시 말하면 (TComponent* Owner,int val) 형태의 생성자는 *.dfm 의 리소스가 없이
    오로지 Coding으로만 폼을 만들때 사용합니다.
    코딩으로만 Form을 만들어서  TForm(TComponent* Owner) 형태의 생성자를 호출하면 에러가 납니다.
    이럴때 TForm((TComponent* Owner , int  val) 형태의 생성자를 호출하면...
    에러없이 폼이 만들어지죠...


그러므로 결론을 지으면

1. 생성자의를 오버라이드 할때
그냥 방법1처럼  형태를 TComponent *Owenr , int 형 만 피하면 됩니다.
방태윤님 말처럼 순서만 바꿔도 해결되죠

2. 그리고 c++Builder나 Delphi에서 wizard로 폼을 만들지 않고
    Coding으로만 Form-Class를 만들어서 폼을 생성하고자 한다면
    TForm((TComponent* Owner , int  val)  형태의 생성자를 만들어 호출해주시면 됩니다.


그럼...




방태윤 님이 쓰신 글 :
: 제대로 하신것 같습니다. 제가 해도 그렇게 할것입니다.
:
: 그런데 문제는 작동이 안된다는 것이지요,ㅋ
:
: __fastcall TForm2(TComponent* Owner, int inputValue);
:
: 이 부분을 
:
: __fastcall TForm2(int inputValue,TComponent* Owner);
:
: 두 변수 순서를 바꾸어 보세요.
:
: 좀 황당하지만 그렇게 하면 됩띠다... 왜 그런지는 모르지만요.
:
: (빌더6 기준입니다)
: (bds2006도 그러네.ㅋ)
:
: 빌더초보 님이 쓰신 글 :
: : 고수님들 안녕하세요.
: :
: : 빌더를 접한지 얼마되지 않은 초보입니다.
: :
: : 폼 생성자의 오버로드 문제 때문에 이렇게 문의를 드립니다.
: :
: :
: : 보통 한 application에서 두개 이상의 폼을 생성하여 show를 시킬 때
: : 이렇게 썼었거든요.
: :
: : 1)   File -> New -> Form  해서 새로운 폼을 하나 추가시킴
: :
: : 2)   Project -> Options -> Forms  에서 새로 추가시킨 폼을
: :      Auto-create forms:  에서 Available forms: 로 이동시킴
: :
: : 3)   원하는 곳에서 다음 구문을 추가하여 폼 생성함
: :
: :      if( tempForm == NULL ) tempForm = new TtempForm(this);
: :           tempForm->Show();
: :
: : 여태까지 이런식으로 새로운 폼을 생성 & Show 를 했습니다.
: :
: :
: :
: : 보통 폼의 생성자가
: :     __fastcall TForm2(TComponent* Owner); 
: :
: : 이렇게 되어있는데
: :
: :
: :
: : 저는
: :     __fastcall TForm2(TComponent* Owner, int inputValue);
: :
: : 이런 형태를 가진 폼 생성자가 필요합니다.
: :
: :
: : 그래서 다음과 같이 했습니다.
: :
: : 1)   File -> New -> Form  해서 새로운 폼을 하나 추가시킴
: :
: :
: :
: : 2)   Project -> Options -> Forms  에서 새로 추가시킨 폼(Form2)을
: :      Auto-create forms:  에서 Available forms: 로 이동시킴
: :
: :
: :
: : 3)   Unit1.cpp 파일 상단에 다음 구문을 추가함
: :
: : #include <vcl.h>
: : #pragma hdrstop
: :
: : #include "Unit1.h"
: : #include "Unit2.h"    --->  새로 추가함.
: :
: :
: :
: : 4)   Unit2.h 파일에 다음 구문을 추가함
: :
: : class TForm2 : public TForm
: : {
: : __published:    // IDE-managed Components
: : private:    // User declarations
: : public:        // User declarations
: :     __fastcall TForm2(TComponent* Owner);
: :     __fastcall TForm2(TComponent* Owner, int inputValue);          --->  새로 추가한 내용
: : };
: :
: :
: :
: : 5)   Unit2.cpp 파일에 다음 구문을 추가함
: : __fastcall TForm2::TForm2(TComponent* Owner, int inputValue)
: :     : TForm(Owner)
: : {
: :     ShowMessage(IntToStr(inputValue);
: : }
: :
: :
: :
: : 6)  Form1 에 Button 콤퍼넌트를 추가시키고 다음과 같은 Click 이벤트를 추가함
: :
: : void __fastcall TForm1::Button1Click(TObject *Sender)
: : {
: :      if( Form2 == NULL ) Form2 = new TForm2(this, 2);
: :         Form2->Show();
: : }
: :
: :
: : 이렇게 해서 컴파일을 시키면 에러없이 컴파일이 완료됩니다.
: : 하지만 Form1에 있는 버튼을 누르면
: : 다음과 같은 에러창이 뜹니다.
: :
: :
: : [Debugger Exception Notification]
: : ------------------------------------------------------------------------
: : Project Project1.exe raised exception class EStackOverflow with message
: : 'Stack overflow', Process stopped.
: : Use Step or Run to continue
: :                       [OK]              [Help]
: : ------------------------------------------------------------------------
: :
: :
: : 제가 무엇을 잘못했는지...
: : 그리고 해결책은 무엇인지 알려주시면 감사하겠습니다.
: :
: : 고수님들 부탁드립니다.

+ -

관련 글 리스트
52094 폼 생성자 오버로드 문제에 대해 문의드립니다. 빌더초보 1387 2008/01/28
52100     Re:폼 생성자 오버로드 문제에 대해 문의드립니다. 방태윤 1142 2008/01/28
52101         Re:Re:폼 생성자 오버로드 문제에 대해 문의드립니다. 장성호 2080 2008/01/29
52109             답변 감사합니다. (_ _) 빌더초보 912 2008/01/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.