線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2168
推到 Plurk!
推到 Facebook!

建立VCL動態二維陣列有錯誤, 無法了解

尚未結案
joney
一般會員


發表:3
回覆:6
積分:1
註冊:2003-04-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-04-27 22:11:10 IP:61.219.xxx.xxx 未訂閱
我使用
TCheckBox **CB;    CB = new TCheckBox*[H];
for (i=0; i< H; i  )
    CB[i] = new TCheckBox[W];
卻在最後一行發生錯誤 訊息為: Cannot find default constructor to initialize array element of type 'TCheckBox'. 這是為什麼呢? 我用int **來產生就沒問題? 經過我的測試要改成以下的方式才可以:
TCheckBox ***CB;    CB = new TCheckBox**[H];
for (i=0; i< H; i  )
    CB[i] = new TCheckBox*[W];
for (i=0; i< H; i  )
for (j=0; j< W; J  )
    CB[i][j] = new TCheckBox(this);
}}
我不知道,如此的做法,是否會產生不可預期的錯誤? 在清除記憶體的方面, 第一種的做法為:
for (i=0; i
但是我不知道,第二種方式產生的陣列要怎麼殺,所以同樣用上面的清除法.
這點請教各位要怎麼做比較好呢?
感謝您的幫忙~    軟體版本是
        
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-04-27 22:26:58 IP:61.231.xxx.xxx 未訂閱
joney您好:   參考看看這個是不是您要的   http://delphi.ktop.com.tw/topic.php?TOPIC_ID=18752 順心 <>~我也是在學習的階段,所以請您多多見諒與指教~ 發表人 -
Royce520
高階會員


發表:18
回覆:157
積分:100
註冊:2002-09-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-04-27 22:49:42 IP:61.216.xxx.xxx 未訂閱
joney 你好,   你要建立動態二維陣列, 當然第一種做法是錯誤的, 不對的地方   有好幾個, 首先 CB 它只能接受 一維陣列的配置, 所以你第二個方法   是對的, 再這裡我建議另一種做法(這樣比較省記憶體, 操作上也比較   簡單 :p), 如下程式碼:    假設 int H = 4; int W = 6;    TCheckBox** CB; CB = new TCheckBox*[H*W]; for ( int i=0; i< H*W; i++) // 至於你提到的錯誤 即是 TCheckBox的建構子 至少要有依個參數    CB = new TCheckBox(this); 如存取 第(3, 4)個元素, 則可這樣取得 CB[(3-1)*W (4-1)], //刪除動作 for ( int i=0; i< H*W; i ) delete CB[i]; delete[] CB; <>[> 發表人 -
------
不要忘記呼吸,不要忘記編程! ∩__∩
joney
一般會員


發表:3
回覆:6
積分:1
註冊:2003-04-27

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-04-28 03:02:00 IP:61.219.xxx.xxx 未訂閱
感謝兩位的解答 原來元件的雙指標只能以一維的方式來產生 我也考慮過用一維的方式 只是看起來不直覺 當然用二維的方式比較浪費記憶體 ^^ 小測試程式而已,沒那麼計較囉 另外,當我在Form1中按Button動態產生一個From2及Button2 Button2去繼承From2 那想再click這個Button2後, 關掉這個Form2 有什麼好方法嗎? 我在Button2 click的function中, 用Form2->Close(); 都會產生錯誤耶. 只能用Form2右上角的x來關~ 發表人 - joney 於 2003/04/28 03:03:52
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-04-28 09:21:49 IP:61.224.xxx.xxx 未訂閱
引言: 感謝兩位的解答 原來元件的雙指標只能以一維的方式來產生 我也考慮過用一維的方式 只是看起來不直覺 當然用二維的方式比較浪費記憶體 ^^ 小測試程式而已,沒那麼計較囉
這樣的說法並不是很正確喔... 您已說過,當改成 int 時,就 Ok ,但用 VCL 元件時就不行! 那是因為 int *intArray=new int[100]; 用一維的整數指標就以操作一維整數陣列, 但對 VCL 本來就只能用指標操作,也就多了一維,如: TCheckBox *CB=new TCheckBox(Form1); 這樣就是只有一個 TCheckBox 可以使用,如果要一維,那就
TCheckBox **CBArray=new TCheckBox*[N];
for(int i=0;i < N ;i  )
  CBArray[i]=new TCheckBox(Form1);
如果要二維,那就
TCheckBox ***CBArray=new TCheckBox**[N];
for(int i=0;i < N ; i   )
  CBArray[i]=new TCheckBox*[M];
for(int i=0;i < N ; i   )
  for(int j=0;j < M ; j   )
     CBArray[i][j]=new TCheckBox(Form1);
用真的二維是比較浪費記憶體,因此選用一維來模擬也是一種方法,但不是唯一。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-04-28 09:25:01 IP:61.224.xxx.xxx 未訂閱
引言: 另外,當我在Form1中按Button動態產生一個From2及Button2 Button2去繼承From2 那想再click這個Button2後, 關掉這個Form2 有什麼好方法嗎? 我在Button2 click的function中, 用Form2->Close(); 都會產生錯誤耶. 只能用Form2右上角的x來關~
可以試試將
Form2->Close();
改成
this->Close();
沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-04-28 09:38:29 IP:61.224.xxx.xxx 未訂閱
引言: 如果要二維,那就
TCheckBox ***CBArray=new TCheckBox**[N];
for(int i=0;i < N ; i   )
  CBArray[i]=new TCheckBox*[M];
for(int i=0;i < N ; i   )
  for(int j=0;j < M ; j   )
     CBArray[i][j]=new TCheckBox(Form1);
回到您最初的問題:delete 二維 VCL ? delete 的方法很簡單,只要按 new 的方式反序去 delete 即可,如下:
for(int i=0;i < N ; i   )
  for(int j=0;j < M ; j   )
     delete CBArray[i][j];
for(int i=0;i < N ; i   )
  delete [] CBArray[i];
delete [] CBArray;
沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
joney
一般會員


發表:3
回覆:6
積分:1
註冊:2003-04-27

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-04-28 13:18:42 IP:203.75.xxx.xxx 未訂閱
感謝dllee老師的回答 原來元件的宣告本身就是一個指標 所以才必需要用三指標來做二維陣列    對於老師所提,以 Form2->Close(); 或 this->Close(); 來關閉Form2, 這我都有試過 但結果是: 第一種方式會產生錯誤 第二種方式會關掉整個Form1, 也就是整個程式結束 這我可以理解, this指的是目前的Form1    另用
for(int i=0;i < N ; i   )  
for(int j=0;j < M ; j   )     
    delete CBArray[i][j];
for(int i=0;i < N ; i   )
    delete [] CBArray[i];
delete [] CBArray;
刪除這個三指標的CBArray會產生錯誤 但用我先前所述刪二層的方法,就可以 我現把整個架構描述一下 主頁是Form1 其中有一個Button1 click Button1 會call一個function A A 會動態產生一個Form2, 一個二維的CheckBox 陣列 CB, 及一個Button2 CB 與 Button2 的parent指向 Form2 在Button2 click後, 會處理 CB 的狀況map到另一個int二維陣列, 然後close Form2.
...B1Click(){
    A()
}    ... A()
{
    TButton   *B2;
    TForm2    *Form2;
    TCheckBox ***CB;        B2    = new ... ;
    Form2 = new ... ;
    CB    = new ... ;
    X     = new ... ;
    :
    :        for (i ...
    for (j ...
        CB[i][j] = ...
    }}        delete CB...
    delete B2;
    delete Form2;
}    ...B2Click()
{
    //處理CB與int二維陣列的map
    close form2;
}
目前的問題就是 1. delete元件的碼, 放的地方對嗎? 2. 如何在按下B2後關閉Form2呢? 感謝大家的幫忙 ~
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-04-28 13:29:47 IP:61.224.xxx.xxx 未訂閱
如果方便的話,可以將 project 上傳嗎?    我以為您的 Button2 是在 Form2 內,而 Form2 又是動態產生, 才會請您試試 this->Close(); 此時的 this 自然是動態產生的 Form2。    另外,二維 VCL 的 new 與 delete 我已試過,並不會有任何問題。    沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/04/28 13:45:59
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-04-28 14:03:44 IP:61.224.xxx.xxx 未訂閱
引言:
... A()
{
    TButton   *B2;
    TForm2    *Form2;
    TCheckBox ***CB;        B2    = new ... ;
    Form2 = new ... ;
    CB    = new ... ;
    X     = new ... ;
    :
    :        for (i ...
    for (j ...
        CB[i][j] = ...
    }}        delete CB...
    delete B2;
    delete Form2;
}
您不可能在同一個 functionA 中又 new 出表單、按鈕、CheckBox,後就 delete,這樣不是才 new 出就刪除,那要如何用呢? 如果 functionA 只是負責 new ,那所有 new 出來的元件是要給別人用的話,那 CB/B2/Form2 的指標都應該是 Form1 的屬性或是整體變數,否則 new 完後指標沒有存下,就無法 delete 了。而當 Form2 的指標已有另存,就可以叫用 Form2->Close(); 將這個 new 出來的 Form2 刪除。 我想看一下您的 code 是因為大部分動態產生表單都會犯下一個錯誤,那就是.... 不知道您有沒有看過 Unit1.hpp 或是 Unit2.hpp 的最後幾行呢?
//----------------------------------------------------------------------------//
extern PACKAGE TForm1 *Form1;
//----------------------------------------------------------------------------//
#endif
 
//----------------------------------------------------------------------------//
extern PACKAGE TForm2 *Form2;
//----------------------------------------------------------------------------//
#endif
其中,的 Form2 如果不小心使用,那就會有很大的問題! 最好 new 出來的不要叫 Form2 以免混淆,或是,將該行 remark 起來,同時將 Unit2.cpp 中
TForm2 *Form2;
也 mark 起來,以減少問題。 而動態表單,內容也全部動態... 當然是不錯,但固定的部分,例如您的 B2 是要 close Form2 ,就可以直接在 Form2 上放一個 Button 也寫好其 Click 就是作 this->Close(); 那就不需要在 Form1 傷腦筋,同時這樣也比較模組化,Form2 的 code 都放在 Form2 Unit 內,而非 Form1 Unit 內。甚至這些 CheckBox 的陣列,也可以放在 Form2 內,在 Create 時可以先叫用 Initialize 或類似名稱的函式,將參數傳入,類似:
TForm2 *myForm2=new TForm2(Application);
...
myForm2->Initialize(10,5); // 動態建出 10 x 5 的 Check Box
myForm2->Show();
...
而 delete 的部分,則可以放在 Form2 的 FormDestroy 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/04/28 14:07:44
------
http://www.ViewMove.com
joney
一般會員


發表:3
回覆:6
積分:1
註冊:2003-04-27

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-04-29 00:25:53 IP:61.219.xxx.xxx 未訂閱
請問一下我要如何將project上傳?    我己經更改了做法, 如老師所述 我事先有了Form1 跟 Form2 兩個.cpp互相include .h檔 而我在Form1中有兩個Edit_e1, Edit_e2 跟Button_A 在Form2中有三個Botton及一個動態產生CheckBox二維陣列的Function_X(int,int) 我在Button_A的click事件中做:
int i= Anistring(Edit_e1->Text).ToInt();
int j= Anistring(Edit_e2->Text).ToInt();
Form2->Function_X(i,j);
Form2->ShowModal();
在Form2的Function_X(int,int)
void __fastcall TForm2::Function_X(int seH, int seW)
{
    int i, j;
    int H = seH;
    int W = seW;        if (H < 3 || W < 3 )
        ShowMessage("Warning: either Height or Width is too small !!");
    else {            if (H%2 == 0) H = H   1;
        if (W%2 == 0) W = W   1;
        seHeight = H;
        seWidth  = W;            Form2->AutoSize = true;
        Form2->Top  = Form1->Top    100;
        Form2->Left = Form1->Left   100;            GroupBox_Matrix->Height = 15   H*30;
        GroupBox_Matrix->Width  = 15   W*30;            Button_Full->Top   = GroupBox_Matrix->Height - (25 (25 4)*2);
        Button_Full->Left  = GroupBox_Matrix->Width   5;
        Button_Clear->Top  = GroupBox_Matrix->Height - (25 (25 4));
        Button_Clear->Left = GroupBox_Matrix->Width   5;
        Button_OK->Top     = GroupBox_Matrix->Height - 25;
        Button_OK->Left    = GroupBox_Matrix->Width   5;            CBmatrix = new TCheckBox**[H];
        for (i=0; i< H; i  )
            CBmatrix[i] = new TCheckBox*[W];            for (i=0; i< H; i  ) {
        for (j=0; j< W; j  ) {
            CBmatrix[i][j] = new TCheckBox(this);
            CBmatrix[i][j]->Parent = GroupBox_Matrix;
            CBmatrix[i][j]->Caption = " ";
            CBmatrix[i][j]->Name = "CB_"  IntToStr(i)  "_"  IntToStr(j);
            CBmatrix[i][j]->Top  = 15   i*30;
            CBmatrix[i][j]->Left = 15   j*30;
            CBmatrix[i][j]->Height = 15;
            CBmatrix[i][j]->Width  = 15;
            CBmatrix[i][j]->Font->Name = "MS Sans Serif";
        }
        }
        CBmatrix[H/2][W/2]->Checked = true;
        CBmatrix[H/2][W/2]->Enabled = false;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormDestroy(TObject *Sender)
{
    for (int i=0; i< seHeight; i  )
    for (int j=0; j< seWidth ; j  )
        delete CBmatrix[i][j];
    for (int i=0; i< seHeight; i  )
        delete[] CBmatrix[i];
    delete[] CBmatrix;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button_OKClick(TObject *Sender)
{
    this->Close();
}
//---------------------------------------------------------------------------
其中在Unit2.h裏宣告 TCheckBox ***CBmatrix; 流程就是 Form1 => 在e1, e2 輸入數字 => 按下Button_a show 出 Form2, 會動態在Form2上產生 e1*e2 大小的CheckBox 二維陣列元件 按下 Form2 中的 Button_OK, 會清除掉CheckBox 二維陣列的記憶體,並關掉Form2 如此循環 但情況是CheckBox沒清掉, 第二次的Form2在產生CheckBox 二維陣列時, 就會出現CheckBox 元件的名稱己存在的錯誤,到底要在那裏刪CheckBox 二維陣列才對呢? 又如果, 我的TCheckBox不是宣告為global變數, 而是放在Finction_X裏宣告, 要怎麼在別的function中去刪除這些元件呢? 發表人 - joney 於 2003/04/29 00:29:37
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-04-29 00:35:20 IP:140.135.xxx.xxx 未訂閱
joney您好:   上傳的方式請參考:  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=19268 順心 <>~我也是在學習的階段,所以請您多多見諒與指教~
joney
一般會員


發表:3
回覆:6
積分:1
註冊:2003-04-27

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-04-29 08:57:39 IP:61.219.xxx.xxx 未訂閱
感謝taishyang, 我己經將project上傳了 謝謝各位無私的幫忙 ^^
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-04-29 10:01:17 IP:61.231.xxx.xxx 未訂閱
在您的 code 中,把 delete 的部分放在: void __fastcall TForm2::FormDestroy(TObject *Sender) 或 void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action) 其實都是不對的,應該放在 OnHide 事件就沒有問題了 void __fastcall TForm2::FormHide(TObject *Sender)    在您的 code 中,把 delete 的部分放在: void __fastcall TForm2::FormDestroy(TObject *Sender) 或 void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action) 其實都是不對的,應該放在 OnHide 事件就沒有問題了 void __fastcall TForm2::FormHide(TObject *Sender)    您應該設一下中斷點就可以發現原本的 code 中,按下 OK 時, FormDestroy 或 FormClose 都是不會被觸發的。等於您 new  出來的都沒有 delete 又要 new 一次那自然就不行囉。    沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/04/29 10:03:37
------
http://www.ViewMove.com
系統時間:2024-04-26 12:32:24
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!