在Symbian中開發C++的注意:
1. 在Symbian中可以使用C++的文法, 除了異常(try-catch)與STL外
不支援異常是因為如果使用標準C++的異常機制會比較費系統資源, 所以Symbian提供了自己的異常架構,那就是(Leave-TRAPED).
不支援STL是因為STL使用的是模板, 編譯時間會進行擴充, 這樣增大了可執行檔的大小
2. Symbian中對C中的基本類型提供了另一套名字, 如unsigned int 可以寫成TUint等, 你可以使用老的方式, 但是為了代碼的可讀性, 最好使用Symbian中自訂的類型. 自訂的類型一般是前面加一個T, 如TInt來代替int (typedef signed int TInt), 它對所有的基本類型都使用了這樣的Typedef, 不過要注意的是 TChar是一個類, 另外還定義了一個TRefByValue, 這個可看成是一個類的引用
3. Symbian中API的對符串使用描述符(Descriptor)來儲存,你當然可以繼續使用普通C語言的形式, 但是調用API時需要對它進行轉換.
另外Symbian中使用的字串是Unicode類型的.
Descriptor中儲存了串的長度資訊, 避免記憶體訪問越界. 有兩個基類TDes 和TDesC派生出其它字串類, 它們相當於 wchar_t* 和 const wchar_t*.
如果想定義一個字串常量, 使用 _L("字串") 就可以
如果想定義一個8bit的字串常量, 使用_L8("字串")
Symbian中描述符與C++的字元類型對應關係:
名稱: Symbian C++
指標 TPtr/TPtrC wchar_t*/const wchar_t*
數組: TBuf/TBufC wchar_t[]/const wchar_t[]
記憶體堆: HBufC8 new wchar_t[]
常量: _L("字串") "字串"
4. 在Symbian中 Symbian中系統API都是類形式提供的. Symbian使用的是C/S架構, 多數操作需要先串連到伺服器再進行操作, 如開啟檔案, 普通開發中使用fopen就可以, 而在Symbian中, 需要這樣做:
RFs fs; // 聲明伺服器連線物件
RFile file; // 定義檔案操作對象
if(fs.Connect() != KErrNone ) // 串連到檔案伺服器
return false;
if( file.Open(fs,L"Filename.txt",
EFileStream|EFileWrite|EFileShareAny) == KErrNone ){
// 開啟檔案
做其它操作
file.Close(); // 關閉檔案
}
fs.Close(); // 關閉到檔案伺服器的串連
對多數系統資源的使用多數也是這樣. 這個是與普通C中不同的地方,開發時要注意一下SDK文檔.
5. Symbian中資源是有限的, 如堆棧只有8k, 所以應該盡量在堆中分配記憶體, 堆棧的錯誤很難檢查.
但是頻繁的new, 會導致記憶體片段, 從而降低程式的效能, 並有可能引起系統不穩定.
6. 由於資源有限, 所以建立類對象時可能失敗, 為了避免由於構造到一半時失敗而引起的資源瀉漏, Symbian中對於對象的構造使用兩步構造的方法. 建構函式中不申請資源, 另外定義一個Construct()或ConstructL()函數在裡面進行其它的初始化操作.
下面是一個例子:
CCommandsView::CCommandsView()
{
m_p = NULL; // 只初始設定變數, 不分配資源
}
CCommandsView::ConstructL()
{
m_p = new(ELeave) char[100]; // 分配資源, 可能會分配失敗而退出
}
CCommandsView* CCommandsView::NewLC(CQikAppUi& aAppUi)
{
CCommandsView* self = new (ELeave) CCommandsView(aAppUi); // 只構造
CleanupStack::PushL(self);
self->ConstructL(); // 進行其它的初始化操作
return self;
}
7. Symbian中提供了cleanup stack來代替標準c++的異常, 如果分配一個資源, 應該把它放到cleanup stack中, 避免異常退出時引起的資源問題(如上面的CleanupStack::PushL(self)).
如下:
CCommandsView* p1 = CCommandsView*::NewLC(ui); // 申請並放到clean up stack 中
CCommandsView* p2 = CCommandsView*::NewLC(ui);
CCommandsView* p3 = CCommandsView*::NewLC(ui);
CleanupStack::PopAndDestroy(3); // 釋放
在每次NewLC中, 都把當前的資源放到cleanup stack中,最後的PopAndDestroy(3)表示刪除前面三個放進去的資源, 相當於執行下面這句話
delete p1;delete p2; delete p3;
如果在p2->NewLC時產生了異常, 那異常會退到上一層, 一直到TRAPD的地方, 然後在這裡p1 的資源被釋放. 這就是cleanup stack的意義(當產生異常時, 保證資源被釋放)
如果一個函數名後面是L結束,表示這個函數是會leave的, 如果它是LC結束,表示它是會leave, 但是它在裡面已經把指標放到cleanup stack中了. 如果沒有這兩個, 表示這函數不會產生異常,也沒有把自己放到cleanup stack中.
6. Symbian中提供了使用中的物件(active object, 一個調度器管理多個對象, 當某個對象啟用時,調度器運行它, 從而實現依並發功能) 與清除堆棧(cleanup stack, 這個是用來代替C++異常的東東)兩個功能, 對於系統線程(如UI中點擊時的處理函數等)預設是建立好這兩個東西. 如果自己建立了線程並想使用它們的話, 需要自己建立.
下面是一個例子:
TInt CMyClass::StartAppThreadFunction(TAny* /*aParam*/)
{
// 建立活動調度器
CActiveScheduler * scheduler = new CActiveScheduler();
if( scheduler == NULL )
return KErrNoMemory;
CActiveScheduler::Install(scheduler);
// 建立清除堆棧
CTrapCleanup * cleanup = CTrapCleanup::New();
TInt err;
if( cleanup == NULL )
err = KErrNoMemory;
else
TRAP( err, RunFunctionL() ); // 運行部分
delete cleanup;
delete CActiveScheduler::Current();
return err;
}
9 Symbian 9 中, 每個api必須有相應的能力才能調用, 能力的指定在簽名中,開發時必須注意
10 Symbian中 dll不可以使用靜態變數或是全域變數, 如果你希望在dll中儲存一些全域的東西可以考慮tls
沒有異常支援及stl支援對於多數開發人員來說還是比較方便的
但是:
symbian中並完全支援標準c庫的函數 (多數c庫的函數是通過封裝symbian的api來實現的, 可能會有少量的api沒有封裝)
棧只有8k
及dll中不可以有靜態或全域變數 這個使在程式中直接使用第三方庫提供了困難
如果想使用第三方庫時需要考慮這點
轉自http://wushuangli.blog.hexun.com/6625886_d.html