一、引言
C++ Buidler和Dephi同為RAD的典范,它使得快速、高效、方便地開發程序成為可能。但是在使用C++ Buidler的過程中發現,不是僅僅熟悉C++ Buidler的VCL組件就能順利地完成程序的編寫,還需要注意一些容易忽視的細節。本文列舉了一些遇到的問題,並提供解決辦法,以供參考借鑒。
二、具體問題及解決辦法
1.使用SQL語句操作數據庫時,如果語句中出現了變量,同一變量不能進行重復使用
如:需訪問數據表T1和T2中符合條件T1.T1_F1="01"及T2.T2_F1="01"的紀錄,按照常規思維,只需在SQL語句中設置一個變量p,分別用來判斷T1.T1_F1和T2.T2_F1的值是否為"01",BCB語句如下: if(ADOQuery1->Active)
{ ADOQuery1->Close();
ADOQuery1->SQL->Clear(); }
ADOQuery1->SQL->Text="SELECT * FROM T1, T2 WHERE T1.T1_F1=:p AND T2.T2_F1=:p";
ADOQuery1->Parameters->ParamValues["p"]="01";
ADOQuery1->Open();
但是在運行這段代碼後,查詢的結果為空。(在訪問Access2003過程中得到證實)通過追蹤SQL語句中的變量p,發現第二次調用p時,BCB沒有對p賦值,即p為NULL;所以得不到期待的查詢結果。正確的參數設置應該為: ADOQuery1->SQL->Text="SELECT * FROM T1, T2 WHERE T1.T1_F1=:p1 AND T2.T2_F1=:p2";
ADOQuery1->Parameters->ParamValues["p1"]="01";
ADOQuery1->Parameters->ParamValues["p2"]="01";
從上面可以看出,BCB對SQL語句中出現的每個賦值變量只使用一次。即使需要在SQL語句中對出現兩次的變量賦予相同的值,也要申請兩個變量,分別賦值。
2. goto語句的使用
在C++ Builder的goto語句中,如果保留字goto與目標標識之間有本地變量的初始化語句: goto EndMark;// EndMark為目標標識
int a=1;
……
EndMark:;
則運行goto語句時會報錯,這給goto語句的使用帶來不便,但如果在goto與目標標識之間加上一對花括弧,則可順利運行: goto EndMark;
{ int a=1;
…… }
EndMark:;
C++ Builder將{……}內的變量初始化理解為局部變量的初始化,局部變量的初始化不會對{ }外面的語句有影響。所以適當地使用花括弧,就可以消除C++ Builder對goto語句使用的限制。
3. 動態創建窗口帶來的影響
動態創建窗口的好處是在不需要該窗口時可以用delete命令釋放內存。但是由於窗口是在內存中完成創建和釋放,也存在一些問題。如:在新建的Application中建立Form1、Form2和Form3,Form1上設有Button1和Edit1、Memo1,Form2上設有Button21、Button22和Edit2、Memo2,Form3上設有Button3和Edit3、Memo3.Form1->Button1的Click事件中動態創建窗口Form2,並設置Form2->Button21的Click事件顯示窗口Form3,且Form1、Form2、Form3分別各有一個Edit1和Memo1,現在試圖通過點擊Form3上的Button3按鈕分別將Edit3和Memo3中的文字賦給Form2的Edit2和Memo2構件,再通過點擊Form2上的Button22按鈕把Edit2和Memo2中的文字賦給Form1.
Form1中的函數: void __fastcall TForm1::Button1Click(TObject *Sender)
{ TForm2 * Form2_N=new TForm2(Form1);
Form2_N ->ShowModal();
delete Form2_N; }
Form2_N中的函數 void __fastcall TForm2_N::Button21Click(TObject *Sender)
{ Form3->ShowModal();
}
void __fastcall TForm2_N::Button22Click(TObject *Sender)
{ Form1->Edit1->Text=Form2->Edit2->Text;
Form1->Memo1->Text=Form2->Memo2->Text;
this->Close(); }
Form3中的函數: void __fastcall TForm3::Button3Click(TObject *Sender)
{ Form2->Edit2->Text=Form3->Edit3->Text;
Form2->Memo2->Text=Form3->Memo3->Text;
this->Close(); }
測試中發現,Form3上Edit3和Memo3中的文字不能賦值到Form2_N的Edit2和Memo2中,但Form2_N上Edit2和Memo2中的文字可以賦到Form1上的Edit1和Memo1中。
如果修改Form1中Button1的Click事件的執行語句,將創建Form2_N改為創建Form2,並將在其它地方出現的Form2_N改為Form2: void __fastcall TForm1::Button1Click(TObject *Sender)
{ Form2=new TForm2(Form1);
Form2->ShowModal();
delete Form2; }
這樣,Form3上Edit3和Memo3中的文字就能賦給Form2的Edit2和Memo2了。
創建屬於TForm2類的窗口Form2_N和Form2時,不同點在於,在創建Form2_N時(點擊Button1時),需要向系統申請內存創建。Form2_N的創建過程 “TForm2 * Form2_N=new TForm2(Form1);”中包含了定義新的窗體類Form2_N和對其進行初始化兩個動作, Form2_N在定義過程中申請了內存空間;而Form2是在Design-Time定義的窗體,在程序初始化時就完成了申請內存空間的動作。兩種窗體申請內存的時間先後影響了它們對所傳遞數值的接受。
三、結語
C++ Builder中有些隱含的使用限制還不太直觀,像動態窗口的創建會給窗口之間的變量賦值帶來不便,而在Delphi中創建動態窗口(Form1:=TForm1.Create(self);)就不存在這樣的問題。因此如果遇到在C++ Builder中的不能用一般方法解決的一些問題時,還需要進一步熟悉C++ Builder,細致分析,多進行嘗試摸索解決,積累了一些經驗,就可以提高編碼效率。