開始學習 firstAppView.cpp

 

/*

 ============================================================================

 Name      : firstAppView.cpp

 Author    : 寶傑

 Copyright   : Your copyright notice

 Description : Application view implementation

 ============================================================================

 */

 

// INCLUDE FILES

#include <coemain.h>

#include "firstAppView.h"

 

// ============================ MEMBER FUNCTIONS ===============================

 

  建一個默認工程,查看View.Cpp文件;第一次看到下面的兩個函數你一定Confused,其實這個寫法正是Symbian的精華所在。

以前學習Java,我們肯定很少處理堆、棧的概念;注意堆棧絕對要分開說清楚。

從我自己的理解來說,棧在數據結構中用的很多,POP,PUSH我們也都很熟;但是在SC++中,棧的空間相當小,我們不能什麼都在棧中PUSH,對於大的數據,必須要堆。在c++中,當我們看到NEW關鍵字時,就要清楚數據的空間在堆上,我們用Delete來回收,不能再Pop了。

 

關於堆棧詳細可以參考http://www.enet.com.cn/eschool/video/c++/

 

 

 

CfirstAppView* CfirstAppView::NewL(const TRect& aRect)

    {

    CfirstAppView* self = CfirstAppView::NewLC(aRect);//調用下面的函數返回自身類型的指針

    //進棧,注意,該函數的末尾是L (相當於Java的Exception,需要有Try,Catch)

    CleanupStack::Pop(self);

 

    return self;

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::NewLC()

// Two-phased constructor.

// -----------------------------------------------------------------------------

//

CfirstAppView* CfirstAppView::NewLC(const TRect& aRect)

    {

    CfirstAppView* self = new (ELeave) CfirstAppView;

    CleanupStack::PushL(self);

    //下面會分析這個函數,觀察這個Fuc,以LC結尾,也顯示了他出錯時不需要你來回收資源

    self->ConstructL(aRect);

        return self;

    }

 

 

// -----------------------------------------------------------------------------

// CfirstAppView::ConstructL()

// Symbian 2nd phase constructor can leave.

// -----------------------------------------------------------------------------

//

void CfirstAppView::ConstructL(const TRect& aRect)

    {

    // Create a window for this application view

    CreateWindowL();

 

    // Set the windows size

    SetRect(aRect);

 

    // Activate the window, which makes it ready to be drawn

    ActivateL();

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::CfirstAppView()

// C++ default constructor can NOT contain any code, that might leave.

// -----------------------------------------------------------------------------

//

CfirstAppView::CfirstAppView() //構造函數

    {

    // No implementation required

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::~CfirstAppView()

// Destructor.

// -----------------------------------------------------------------------------

//

CfirstAppView::~CfirstAppView() //析構函數

    {

    // No implementation required

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::Draw()

// Draws the display.這個和Java很像的

// -----------------------------------------------------------------------------

//

void CfirstAppView::Draw(const TRect& /*aRect*/) const

    {

    // Get the standard graphics context 感覺上像是 graphic

    CWindowGc& gc = SystemGc();

 

    // Gets the control's extent

    TRect drawRect(Rect()); // Draws and fills a rectangle.

 

    // Clears the screen

    gc.Clear(drawRect);

 

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::SizeChanged()

// Called by framework when the view size is changed.

// -----------------------------------------------------------------------------

//

void CfirstAppView::SizeChanged()

    {

    DrawNow();

    }

 

// -----------------------------------------------------------------------------

// CfirstAppView::HandlePointerEventL()

// Called by framework to handle pointer touch events.

// Note: although this method is compatible with earlier SDKs,

// it will not be called in SDKs without Touch support.

// -----------------------------------------------------------------------------

//

void CfirstAppView::HandlePointerEventL(const TPointerEvent& aPointerEvent)

    {

 

    // Call base class HandlePointerEventL()

    CCoeControl::HandlePointerEventL(aPointerEvent);

    }

 

// End of File

 

本博文結束 如有錯誤 請斧正 諒解!

                                                                                                                             寶傑    文

 

讓我們看看典型的NewL()以及NewLC()的實現:(和我們自己默認工程建的函數是一樣的)

CExample* CExample::NewLC()

{

CExample* me = new (ELeave) CExample(); // First-phase construction

CleanupStack::PushL(me);

me->ConstructL(); // Second-phase construction

return (me);

}

CExample* CExample::NewL()

{

CExample* me = CExample::NewLC();

CleanupStack::Pop(me);

return (me);

}

NewL()工廠函數是用NewLC()函數而不是其他函數(因爲需要一個額外的PushL()調用來把指針推入清除棧,所以效率較低)來實現的。

兩個工廠函數要麼都返回一個完全構造的對象,要麼由於沒有足夠的內存供對象分配(也就是new(ELeave)異常退出)或第二階段的ConstructL()函數由於某種原因而異常退出。這也就意味着,如果一個對象通過兩階段構造被完全初始化,那麼類的實現中就不再需要在每次使用成員變量前都檢查它們是否合法了。換言之,就是如果一個對象存在,那麼它必然已被完全構造出來了。這樣做就得到一種高效的類實現,使得不需要在取消指針的引用之前對每個成員指針進行測試。(還是看的很糊塗,以後慢慢體會)

考慮如下代碼,它爲CfirstAppView類的對象在堆內存上分配了空間,並相應地將其賦給self: 

 

 

 

CfirstAppView* self = new (ELeave) CfirstAppView;

 

 

 

代碼調用new操作符來在內存擁有足夠空閒空間的時候爲CfirstAppView對象分配內存。完成分配以後,調用CfirstAppView的構造函數來初始化對象。但是如果CfirstAppView的構造函數異常退出的話,已經爲self分配的內存空間以及構造函數中可能分配的額外內存都將被孤立。(感覺上是內存泄露的味道)

這就引出了Symbian OS中一個基本的內存管理規則:C++的構造函數永遠也不能異常退出。

但是,通常可能需要編寫一些異常退出的初始化代碼,比如爲存儲另一個對象而分配內存,或者從一個可能已經不存在或已經毀壞的配置文件中讀取信息。有很多初始化可能會失敗的原因,在Symbian OS中相應的解決方法是用兩階段構造。

 

1. 一個不能異常退出的C++構造函數

這個構造函數會被new操作符調用。它顯式地調用基類的構造函數,並且可以調用那些不能異常退出的函數,和/或用默認值或構造函數的參數來初始化成員變量。(比如例子)

2. 一個單獨的初始化方法(典型的名稱是ConstructL())

這個方法可以在分配了內存並且new操作符所創建的對象被推入清除棧時被調用;它將完成對象的創建工作,並以安全的方式執行可能異常退出的操作。如果出現一個異常退出,清除棧會調用析構函數來釋放那些已經成功分配的資源,以及爲此對象本身所分配的內存。

一個類通常會提供一個將兩個構造階段都包含進來的公共靜態函數,併爲此函數取個簡單明瞭的能表達初始化含義的名稱(這樣那兩個用於構造的方法就可以聲明成私有成員或保護成員,以免被不小心誤用了)。這種工廠函數通常被稱作NewL(),它是一個靜態方法,這樣就可以在擁有一個此類的實例之前得以被調用。

感覺上還是不是很懂,似乎在說對象在沒有實例化的時候就會調用構造?不明白。讓我們來看個例子:

 

class CExample : public CBase  //公共靜態函數

{

public:

static CExample* NewL();

static CExample* NewLC();

~CExample(); // Must cope with partially constructed objects

... // Other public methods, e.g. Foo(), Bar()

private:

CExample();          // Guaranteed not to leave

void ConstructL(); // Second-phase construction code, may leave

CPointer* iPointer;

};

注意:類CExample也有一個NewLC()方法。此方法也是一個工廠函數,但它執行後是在其返回的清除棧上留有一個指針。

 

提示

如果在函數返回時,對象的指針已經被推入清除棧,並依然保留在其中,那麼按照Symbian OS習俗,這個函數名後面應該加字母C。這樣做就暗示了調用者,如果此函數被正確返回,那麼清除棧上還有一個額外的指針。

// -----------------------------------------------------------------------------

// CfirstAppView::NewL()

// Two-phased constructor.

// -----------------------------------------------------------------------------

//

// -----------------------------------------------------------------------------

//

// 這是我的第四篇博文,我也是剛開始學習Symbian c++ 同大家一起努力

// 謹以此文獻給我的最愛 YY女孩(YY 可別想壞了哦)

// 參考鏈接 http://book.csdn.net/bookfiles/1240/100124036914.shtml

// -----------------------------------------------------------------------------

//

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章