开始学习 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

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

//

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