打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
cocos2dx 引擎学习心得
userphoto

2015.04.01

关注

cocos2d-x     深入理解

CCNode类不自带贴图,所以在屏幕上看不到任何节点类的效果,因此一般使用CCNode类的场合有两个,第一个情况就是,需要一个父节点来管理一批子节点,这时候可以设置个无形的子节点来管理自己点;第二个情况就是,有时需要自己定义一个在屏幕上显示的对象,这时候让新定义的这个类继承CCNode。

虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数。注意:如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。简而言之,虚函数允许在程序运行过程中根据指针的类型动态第选择调用指针类型的函数。

CCLayer是CCNode类的子类,并且在此基础上可以实现触屏事件代理协议,可以实现CCNode类的功能,并且可以处理输入,包括触屏和加速度传感器。

几种列表控件  

1. CCTableView 2.CCScrollLayerExt 3.CCListView2.CCScrollayerExt 

CCScrollLayerExt *m_pScorllLayer = newCCScrollLayerExt(CCRect rect);

直接创建一个ScrollLayer,根据展示的资源图片设置位置和点击事件。

CCListView

将变量从int类型转换成字符串类型方法

sprintf

弹出窗创建模板(包含列表控件)demo

点击事件  同一界面上的不同点击事件(im)

ccTouchBegin  ccTouchMovingccTouchEnd ccTouchcanceled 平行移动和垂直移动  根据获取的x和y的大小来判断

子类继承基类时,当基类有虚函数必须继承并实现,否则会报错

Object+C语法

减号表示一个函数、或者方法、或者消息的开始。

加号的意思是其他函数可以直接调用那个这个类中的这个函数,而不用创建这个类的实例

中括号可以认为是如何调用你刚才写的这个方法。

#import 同#include 一样

@interface

 @end

多线程的情况下,访问静态变量我们需要加一些异步机制,防止多个进程同步修改静态变量

2014-01-07 知识点:

单例模式

保证一个类仅有一个实例,并提供一个访问他的全局访问点,该实例被所有程序模块共享。 

注意:

       在c++中可以用一个全局变量作为单例!

  1. class CSingleton: 
  2. {  
  3. // 其它成员 
  4. public:  
  5. static CSingleton GetInstance() 
  6. {  
  7. if (m_pInstance == NULL) 
  8. m_pInstance new CSingleton(); 
  9. return m_pInstance; 
  10. }  
  11. private:  
  12. CSingleton(){};  
  13. static CSingleton m_pInstance; 

它有一个指向唯一实例的静态指针m_pInstance,并且私有化

它有一个共有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。

它的构造函数是私有的,这样就不能从别处创建该类的实例。

程序在结束的时候,系统会自动析构所有的全局变量,事实上,系统也会析构类的静态成员变量。

变量

C++变量根据定义位置的不同,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名作用域和文件作用域。

从作用域看:

全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包括全局变量定义的源文件需要用extern关键字再次声明这个全局变量。

静态局部变量具有局部作用域。它只被初始化一次,自从第一次初始化直到程序与你新内阁结束都一直存在,他和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。

局部变量也只有局部作用域,他是自动对象,他在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用结束后,变量就被撤销,其所占用的内存也被收回。

静态全局变量也具有全局作用域,他与全局变量的区别在于如果程序包含多个文件的话,他作用于定义它的文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同的静态全局变量,他们也是不同的变量。

从分配内存空间看:

全局变量、静态局部变量、静态全局变量都在静态存储区分配空间,而局部变量在栈分配空间。

全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上没有什么不同。区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。

1、静态变量会被放在程序的静态数据存储区里,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是他与堆栈变量和堆变量的区别

2、变量用static告知编译器,自己仅仅在变量的作用域范围内可见。这一点是他与全局变量的区别。

从以上分析可以看出,把局部变量改变为静态变量后是改变了他的存储方式,即改变了他的生存期。把全局变量改变为静态变量后是改变了他的作用域,限制了他的使用范围,因此static这个说明符在不同的地方起的作用是不同的。

TIPS:

1、若全局变量仅在单个文件中访问,则可以讲这个变量修改为静态全局变量。

2、若全局变量仅在单个函数中使用,则可以将这个变量修改为该函数的静态局部变量。

3、全局变量、静态局部变量、静态全局变量都存放在静态数据存储区。

4、函数中必须要使用static变量的情况:当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。

内存释放

在C++中,内存分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区

栈,在执行函数时,函数内部局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动呗释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

自由存储区,就是那些有malloc等分配的内存块,他和堆是十分相似的,不过它使用free来释放的。

全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的c语言中,全局变量又分为初始化的和未初始化的,在C++里没有区分了,他们共同占用同一块内存区。

常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。

int *p = new int[5]; //栈 堆

delete []p;//释放堆内存

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都由专门的指令执行,所以栈的效率比较高,堆则是C/C++函数库提供的,他的机制是很复杂的。

常见的内存错误及其对策 

内存分配未成功,却使用了它

assert(p!=NULL)/if(p==NULL)

内存分配虽然成功,但是尚未初始化就引用它

赋初值

忘记释放内存,造成内存泄露

释放了内存却继续使用它

2014-01-10

2D和3D的区别,如何分辨游戏是2D还是3D?

主流2D和3D引擎有哪些,各是使用什么计算机语言。

多线程实现

C++开发中,并发、异步、缓存

帧动画和骨骼动画的区别,其所应用的方式

2014-01-16

C++面向对象编程 如何定义基类及其子类的实现

函数别名的使用

typedef

typedef并不创建一个新的类型,只是为已有类型定义一个同义字!

2014-01-17

C++ 基类 虚函数 纯虚函数 子类继承基类虚函数的调用等

抽象类是一种特殊的类,它是为了抽象和设计的目的建立的,它处于继承层次的较上层。

抽象类的定义:   

       带有纯虚函数的类为抽象类。

抽象类的作用:   

      抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。

使用抽象类时注意:

      抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。注意:抽象类不能定义对象。

在面向对象语言中,接口的多种不同实现方式即为多态,多态是指,用父类的指针指向子类的实例,然后通过父类的指针调用实际子类的成员函数。

多态性就是允许将子类类型的指针赋值给父类类型的指针,多态通过虚函数实现的。

2014-01-17

lua脚本的使用(与宿主语言的相互调用C++)

lua脚本:

 Lua脚本可以很容易的被 C/C++代码调用,也可以反过来调用C/C++的函数

lua和C程序通过一个堆栈交换数据 struct lua_State

2014-01-20

控件模板的编写(模板类)

注:寻宝界面例子

//崩溃统计软件地址 :

账号 zhangfucai@me-game.com  密码Zfc

https://www.crashlytics.com

2014-01-25

友元类:

使用基类指针的子类对象 调用虚函数,如果基类没有实现,则调用子类的实现部分。

定义接口类    

回调基类   保存回调基类指针的成员变量类    

网络通信模块解析  基类、回调等内容

1、内存的释放   如果是new的 必须手动调用函数释放   

备注:

2014-01-26

内存释放详细(cocos2d-x)

C++对象的创建与释放             (内存的释放)

一  构造函数 

析构函数(destructor)也是一个特殊的成员函数,它的作用于构造函数相反,当对象的生命周期结束时,会自动执行析构函数

class Counter

{

public:

        //特点以类名作为函数名,无返回类型

       Counter()

        {

              m_value =0;

         }

private:

         //数据成员

         intm_value;

}

该对象被创建时,编译系统对对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作!

构造函数的作用: 初始化对象的数据成员

//构造函数的种类 

类的静态成员是可以独立访问的,也就是说,无须创建任何实例对象就可以访问!

非静态成员函数可以在任意地访问静态成员函数和静态数据成员

构造函数的特点:

1 构造函数的命名必须和列明完全相同,在java中普通函数可以和构造函数同名,但是必须带有返回值

2 构造函数的功能主要用于在类的对象创建时定义初始化的状态

3构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用,一般方法是在程序执行到它的时候被调用

二  析构函数

程序执行析构函数的情况

1如果在一个函数中定义了一个对象(它是自动局部对象),当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。

2 static局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只是在main函数结束时或用exit函数结束程序时,才调用局部对象的析构函数。

3如果定义一个全局对象,则在程序的流程离开其作用域时(如main函数结束或调用exit函数)时,调用该全局对象的析构函数。

4如果用new运算符动态地建立一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。

备注:析构函数不返回任何值,没有函数类型,也没有函数参数。因此它不能被重载,一个类可以有多个构造函数,但只能有一个析构函数。

批量处理问题设计思路

游戏里的建筑物

windows句柄:

C++内存管理

释放了内存却继续使用

1.程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

2.函数的return语句写错了,注意不要返回指向“栈内存”的”指针“或者“引用”,因为该内存在函数体结束时被自动销毁。

3.使用free或delete释放内存后,没有将指针设置为NULL,导致产生“野指针”。

规则1用malloc或new申请内存后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存。

规则2 不要忘记为数组和动态内存赋初值,防止将未被初始化的内存作为右值使用。

规则3 避免数组或指针的下标越界,特别要当心发生多1或者少1操作。

规则4 动态内存的申请与释放必须配对,防止内存泄露。

规则5 用free或delete释放内存之后,立即将指针设置为NULL,防止产生“野指针”。

C++之拷贝构造函数

如果类中没有声明拷贝构造函数,则系统将会自动地生成一个缺省的拷贝构造函数,属性为public

在以下两种情况会调用拷贝构造函数

1.当函数的形参是类对象时,这时需要在内存中建立一个局部的对象,系统要讲实参的内容拷贝至形参中,相当于用一个对象来初始化另一个对象,理所当然要调用拷贝构造函数

2.当函数的返回值是类对象时,也要建立一个临时的对象,要将函数返回时的局部类对象的内容拷贝至临时对象的内存中,相当于用一个对象来初始化另一个对象,这种情况也要调用拷贝构造函数。

注意:

局部类对象在离开建立他的函数时就消亡了,不可能在返回调用函数后继续生存,所以编译系统会在调用函数的表达式中创建一个无名的临时对象,该临时对象的生存周期只在函数调用的表达式中,所谓return对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象,如果返回的是变量,处理过程是类似的,只不过不调用构造函数。所以,建议将函数的形参于返回值声明为对象的引用,而不是对象,这样可以减少内存的使用,不仅节省空间,效率也更高

C++迭代器详解

迭代器是一种允许程序员检查容器内元素,并实现元素遍历的数据类型,标准库为每一种标准容器定义了一种迭代器。

基类的虚析构函数

虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

如果某个类不包含虚函数,那一般式表示它将不作为一个基类来使用,当一个类不准备作为基类使用时,使析构函数为虚一般不好,因为它会为类增加一个虚函数表,使得对象的体积翻倍,还可能降低其可移植性。

SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常低。

sqlite_open是sqlite提供的api,打开一个数据库文件,并与一个sqlite句柄关联,如果该文件不存在则创建它,返回值如果是SQLITE_OK则打开成功。

派生类内存的释放   

首先调用自身的析构函数,然后再调用基类的析构函数一级级向上。

程序数据存储

1 Registers寄存器 

这是速度最快的存储场所,因为寄存器与其他所有存储媒介都不同,它位于处理器内部,不过,寄存器的数量十分有限,所以寄存器是根据需要由编译器适当的分配。

2 stack 栈

位于一般的RAM(随机访问内存)中,处理器通过其指针获得处理的直接支持,栈指针若向下(后)移,会分配新的内存,若向上移则会释放那些内存,这是一种特别快,特别有效率的数据存储方式,速度仅次于寄存器。

游戏大数据存储方式/处理方式

C++中的指针:

指针可以用来有效地表示复杂的数据结构,可以用于函数传递并达到更加灵活使用函数的目的。游戏数据缓存实例

定义所有数据缓存类的基类 用于保存数据

class BBData

{

public:

      BBData();

      virtual ~BBData();

      void retain(void);

      void release(void);

      unsigned intretainCount(void);

      void setParent(BBData*parent);

      BBData* getParent();

protected:

      BBData *m_pParent;

      unsigned intm_uReference;

      unsigned int m_uId;

};


#include "BBdata.h"

BBData::BBData()

{

    m_pParent = NULL;

    m_uId = 0;

    m_uReference = 1;

}


BBData::~BBData()

{

    m_pParent = NULL;

    m_uReference = 0;

}


void BBData::release()

{

    assert(m_uReference > 0);

    m_uReference--;

    if(m_uReference == 0 )

    {

         delete this;

    }

}


void BBData::retain()

{

    m_uReference++;

}


unsigned int BBData::retainCount()

{

    return m_uReference;

}


void BBData::setParent(BBData *parent)

{

    m_pParent = parent;

}


BBData *BBData::getParent()

{

     return m_pParent;

}

#ifndef XXQX_BBDataCell_h

#define XXQX_BBDataCell_h


#include "BBData.h"

#include "CCObject.h"

#include


USING_NS_CC;


class BBMonitorInfo;

class BBDataAccess;

class BBDataCell;


typedef bool (BBDataCell::*SEL_GetDataB)();

typedef int (BBDataCell::*SEL_GetDataI)();

typedef void (BBDataCell::*SEL_SetDataB)(bool);

typedef void *(BBDataCell::*SEL_GetData)();

typedef void(CCObject::*SEL_DataChangeCallFuncB)(int, bool);

typedef void(CCObject::*SEL_DataChangeCallFuncI)(int, int);

typedef void(CCObject::*SEL_DataChangeCallFunc)(int);

#define listenercallfunc_selector(_SELECTOR)(SEL_DataChangeCallFunc)(&_SELECTOR)

#define listenercallfuncB_selector(_SELECTOR)(SEL_DataChangeCallFuncB)(&_SELECTOR)

#define listenercallfuncI_selector(_SELECTOR)(SEL_DataChangeCallFuncI)(&_SELECTOR)

#define listenercallfunc_selector(_SELECTOR)(SEL_DataChangeCallFunc)(&_SELECTOR)

#define objectfuncB_selector(_SELECTOR)(SEL_GetDataB)(&_SELECTOR)

#define objectfuncI_selector(_SELECTOR)(SEL_GetDataI)(&_SELECTOR)

#define objectfuncSetB_selector(_SELECTOR)(SEL_SetDataB)(&_SELECTOR)

#define objectfunc_selector(_SELECTOR)(SEL_GetData)(&_SELECTOR)


#define BB_MONITOR_NOTIFY(funcName)dataStatusNotification(*(int *)&funcName)



#define BB_SYNTHESIZE_MONITOR_SET_I(varType,varName, funName ,ClassName)\

protected: varType varName;\

public: virtual varType get##funName(void) { returnvarName; }\

public: virtual void set##funName(varType var) \

{ \

if(varName!=var) {\

varName = var;\

SEL_GetDataI func =objectfuncI_selector(ClassName::get##funName);\

BB_MONITOR_NOTIFY(func);}\

}



#define BB_SYNTHESIZE_MONITOR_SET_B(varType,varName, funName ,ClassName)\

protected: varType varName;\

public: virtual varType get##funName(void) { returnvarName; }\

public: virtual void set##funName(varType var) \

{ \

if(varName!=var) {\

varName = var;\

SEL_GetDataB func =objectfuncB_selector(ClassName::get##funName);\

BB_MONITOR_NOTIFY(func);}\

}



#define BB_SYNTHESIZE_MONITOR_SET(varType, varName,funName ,ClassName)\

protected: varType varName;\

public: virtual varType get##funName(void) { returnvarName; }\

public: virtual void set##funName(varType var) \

{ \

varName = var;\

SEL_GetData func =objectfunc_selector(ClassName::get##funName);\

BB_MONITOR_NOTIFY(func);\

}

 class BBDataCell : publicBBData 

{

public:

   BBDataCell();

   

    virtual~BBDataCell();

   

    virtual boolinit();

   

    virtual voidonEnter();

   

    static stringgetClassName();

   

    static stringgetTableName();

   

    BBDataAccess*getDb();


   

    virtual boolcreateTable();

   

    virtual voidcleanTable();

   

    virtual boolsaveData();

   

    virtual voidreadData( sqlite3_stmt *stm );

   

    booldeleteData();

   

   

    BB_SYNTHESIZE(int, m_uId, Id );

   

private:    

    //multimap fordata change msg

    multimapm_mMonitors;

    //

protected:   

    voiddataStatusNotification(int func);  

public:  

    

    intregisterListener(SEL_GetDataI func , CCObject*listener,SEL_DataChangeCallFuncI callback);

    intregisterListener(SEL_GetDataB func , CCObject*listener,SEL_DataChangeCallFuncB callback);

    intregisterListener(SEL_GetData func , CCObject*listener,SEL_DataChangeCallFunc callback);

    boolunregisterListener(SEL_GetDataI func , CCObject* listener);

    boolunregisterListener(SEL_GetDataB func , CCObject* listener);

    boolunregisterListener(SEL_GetData func , CCObject* listener);


};

//监听某个变量是否改变,如改变发出通知

class BBMonitorInfo

{

private:

    intm_iType;


public:  

    BBDataCell*m_pBeListener;

    CCObject*m_pListener;

   //    union{

   //       SEL_GetDataI m_pGetDataI;

   //       SEL_GetDataB m_pGetDataB;

   //    };

   //    union{

   //       SEL_DataChangeCallFuncI m_pGetDataI;

   //       SEL_DataChangeCallFuncB m_pGetDataB;

   //    };

    SEL_GetDataIm_pGetDataI;

   SEL_DataChangeCallFuncI m_pCallBackI;

    SEL_GetDataBm_pGetDataB;

   SEL_DataChangeCallFuncB m_pCallBackB;  

   SEL_DataChangeCallFunc m_pCallBack;  

   

public:

   

   BBMonitorInfo(BBDataCell* belistener,SEL_GetDataI getdata,CCObject* listener,SEL_DataChangeCallFuncI callback)

    {

       m_iType = 1;

       m_pBeListener =belistener;

       m_pListener = listener;

       m_pGetDataI = getdata;

       m_pCallBackI = callback;

       m_pGetDataB = NULL;

       m_pCallBackB = NULL;

       m_pCallBack = NULL;

    }

   

   BBMonitorInfo(BBDataCell* belistener,SEL_GetDataB getdata,CCObject* listener,SEL_DataChangeCallFuncB callback)

    {

       m_iType = 2;

       m_pBeListener =belistener;

       m_pListener = listener;

       m_pGetDataB = getdata;

       m_pCallBackB = callback;

       m_pGetDataI = NULL;

       m_pCallBackI = NULL;

       m_pCallBack = NULL;

    }

   BBMonitorInfo(BBDataCell* belistener,SEL_GetData getdata, CCObject*listener,SEL_DataChangeCallFunc callback)

    {

       m_iType = 3;

       m_pBeListener =belistener;

       m_pListener = listener;

       m_pCallBack = callback;

       m_pGetDataB = NULL;

       m_pCallBackB = NULL;

       m_pGetDataI = NULL;

       m_pCallBackI = NULL;

    }

   ~BBMonitorInfo(){};

   

    voidnotifyMonitor()

    {

       if(m_pBeListener!=NULL&& m_pListener!=NULL)

       {

          if(m_iType == 1)

          {

             (m_pListener->*(m_pCallBackI))(m_pBeListener->getId(),(m_pBeListener->*(m_pGetDataI))());

          }

          else if(m_iType == 2)

          {

             (m_pListener->*(m_pCallBackB))(m_pBeListener->getId(),(m_pBeListener->*(m_pGetDataB))());

          }

          else if(m_iType == 3)

          {

             (m_pListener->*(m_pCallBack))(m_pBeListener->getId());

          }

          else

          {

             assert(0);

          }

          

       }

    }

     

};


#endif

#include "BBDataCell.h"

#include "BBDataAccess.h"


USING_NS_CC;


BBDataCell::BBDataCell()

{

   m_mMonitors.clear();

}


BBDataCell::~BBDataCell()

{

   multimap::iterator it = m_mMonitors.begin();

    while (it !=m_mMonitors.end())

     

       if(it->second!=NULL) 

       {

          delete it->second;

       }

       it++;

    }

   

   m_mMonitors.clear();

   

}


bool BBDataCell::init()

{

    returntrue;

}


void BBDataCell::onEnter()

{

   //CCNode::onEnter(); 

}


BBDataAccess* BBDataCell::getDb()

{

    if(getParent() && getParent()->getParent() )

    {

       BBDataAccess* dataAccess =dynamic_cast(getParent()->getParent());

       if( dataAccess )

          return dataAccess;

    }

    returnNULL;

}


string BBDataCell::getClassName()

{

    returnNULL;

}


string BBDataCell::getTableName()

{

    returnNULL;

}


bool BBDataCell::createTable()

{

    returntrue;

}


void BBDataCell::cleanTable()

{

}


bool BBDataCell::saveData()

{

    returntrue;

}


void BBDataCell::readData(sqlite3_stmt *stm)

{

   

}


int BBDataCell::registerListener(SEL_GetDataI func ,CCObject* listener,SEL_DataChangeCallFuncI callback)

{

    if (func!=NULL&& listener!=NULL &&callback!=NULL) 

    {

      unregisterListener(func,listener);

       

       BBMonitorInfo* monitorInfo =new BBMonitorInfo(this,func,listener,callback);

       if (monitorInfo !=NULL) 

       {

          //TODO:检查函数指针 func

         m_mMonitors.insert(pair(*(int*)&func,monitorInfo)); 

          return m_uId;

       }

    }

   

    return 0;

}


bool BBDataCell::unregisterListener(SEL_GetDataIfunc , CCObject* listener)

{

    if (func!=NULL&& listener!=NULL) 

        

       int num =m_mMonitors.count(*(int*)&func);

       multimap::iterator it =m_mMonitors.find(*(int*)&func);

       for (int i=0; i

       {

          if (it->first==*(int*)&func&& 

             ((BBMonitorInfo*)it->second)->m_pListener==listener) 

          {

              deleteit->second;

             m_mMonitors.erase(it);

                  

              returntrue;

          }

       }

    }

    returnfalse;

}


int BBDataCell::registerListener(SEL_GetDataB func ,CCObject* listener,SEL_DataChangeCallFuncB callback)

{

    if (func!=NULL&& listener!=NULL &&callback!=NULL) 

    {

      unregisterListener(func,listener);

       

       BBMonitorInfo* monitorInfo =new BBMonitorInfo(this,func,listener,callback);

       if (monitorInfo !=NULL) 

       {

          //TODO:检查函数指针 func

         m_mMonitors.insert(pair(*(int*)&func,monitorInfo));

          

          return m_uId;

       }

    }

   

    return 0;

}


bool BBDataCell::unregisterListener(SEL_GetDataBfunc , CCObject* listener)

{

   

    if (func!=NULL&& listener!=NULL) 

        

       int num =m_mMonitors.count(*(int*)&func);

       multimap::iterator it =m_mMonitors.find(*(int*)&func);

       for (int i=0; i

       {

          if (it->first==*(int*)&func&& 

             ((BBMonitorInfo*)it->second)->m_pListener==listener) 

          {

              deleteit->second;

             m_mMonitors.erase(it);

             

              returntrue;

          }

       }

       

    }

    returnfalse;

}


int BBDataCell::registerListener(SEL_GetData func ,CCObject* listener,SEL_DataChangeCallFunc callback)

{

   assert(func!=NULL && listener!=NULL &&callback!=NULL);

    if (func!=NULL&& listener!=NULL &&callback!=NULL) 

    {

      unregisterListener(func,listener);

       

       BBMonitorInfo* monitorInfo =new BBMonitorInfo(this,func,listener,callback);

       if (monitorInfo !=NULL) 

       {

          //TODO:检查函数指针 func

         m_mMonitors.insert(pair(*(int*)&func,monitorInfo));

          

          return m_uId;

       }

    }

   

    return 0;

}


bool BBDataCell::unregisterListener(SEL_GetData func, CCObject* listener)

{

   

    if (func!=NULL&& listener!=NULL) 

        

       int num =m_mMonitors.count(*(int*)&func);

       multimap::iterator it =m_mMonitors.find(*(int*)&func);

       for (int i=0; i

       {

          if (it->first==*(int*)&func&& 

             ((BBMonitorInfo*)it->second)->m_pListener==listener) 

          {

              deleteit->second;

             m_mMonitors.erase(it);

             

              returntrue;

          }

       }

       

    }

    returnfalse;

}


void BBDataCell::dataStatusNotification(intfunc)

{

//   cout<<this<<endl;

//   cout<<m_mMonitors.size()<<endl;

    if(m_mMonitors.size()<=0) 

       return ;

   

    //int num =m_mMonitors.count(*(int*)&func);

    int num =m_mMonitors.count(func);

   multimap::iterator it = m_mMonitors.find(func);

    for (int i=0;i

    {

       BBMonitorInfo *m =it->second;

       if(m!=NULL) 

       {

          m->notifyMonitor();

       }

    }


}

#ifndef BBFactoryCell_H_HEADER_INCLUDED_AF47CDA7

#define BBFactoryCell_H_HEADER_INCLUDED_AF47CDA7

#include "BBDataCell.h"

#include


#define BBFACTORY_FOREACH( __factory__, __object__ )\

if (__factory__ &&__factory__->getCache().size() > 0) \

for(vector::iterator it =__factory__->getCache().begin();                        \

it != __factory__->getCache().end() &&(__object__ = *it) != NULL;                             \

it++)



// 工厂原型类,定义普通工厂需要的接口。 

//##ModelId=50B80FD20196

class BBFactoryCell : public BBDataCell

{

#define BBFactoryArray vector

public:

   BBFactoryCell(){ m_iMaxCacheSize = 5; }

   

    virtual~BBFactoryCell()

    {

       detachAll();

    }

   

   // 向工厂中加入子节点

    //返回值: false : 队列已满需要清除之后重新插入

    virtual booladdChild(BBDataCell* child);


   // 从工厂中移除子节点

    virtual voidremoveChild(BBDataCell* child, bool bCleanUp = false);

   

   // 清空当前队列,所有缓冲区数据入库

    virtual voiddetachAll();

   

    //缓冲区是否已满

    boolisFull();

   

    //设置缓冲区大小

    voidsetCacheSize( int size );

   

  

    BBDataCell*getChildById( int id );

   

   

    voidmoveObject( BBDataCell* data , int position );


    inline intgetCacheSize()

    {

       return m_cache.size();

    }

   

    inlineBBFactoryArray& getCache()

    {

       return m_cache;

    }

   

    virtual boolsaveData();

   

    virtual voidreadData( sqlite3_stmt *stm );

private:

    unsigned intm_iMaxCacheSize;

   

    //mapm_cache;

   

    BBFactoryArraym_cache;

};

#endif

#include "BBFactoryCell.h"

#include bool BBFactoryCell::addChild(BBDataCell*child)

{

   

   BBFactoryArray::iterator it = find(m_cache.begin(), m_cache.end(),child);

   

    if( it !=m_cache.end() )

    {

       child->retain();

       return true;

    }

   

    if( isFull())

       return false;

   

   m_cache.push_back(child);

   

   child->setParent(this);

   child->onEnter();

   

    returntrue;

}


void BBFactoryCell::removeChild(BBDataCell* child,bool bCleanUp)

{

    if(!child)

       return;

   

    unsigned intreference = child->retainCount();

    if( reference== 1 )

    {

       BBFactoryArray::iterator it =find(m_cache.begin(), m_cache.end(), child);

       

       if( it != m_cache.end() )

          m_cache.erase(it);

       

       delete child;

    }

}


bool BBFactoryCell::isFull()

{

    returnm_cache.size() >= m_iMaxCacheSize ? true : false ;

}


void BBFactoryCell::setCacheSize(int size)

{

   m_iMaxCacheSize = size;

}


void BBFactoryCell::detachAll()

{

    for(BBFactoryArray::iterator it = m_cache.begin(); it != m_cache.end();++it )

    {

       delete *it;

    }

   

   m_cache.clear();

   m_iMaxCacheSize = 10;

}


BBDataCell* BBFactoryCell::getChildById(int id)

{    

    for(BBFactoryArray::iterator it = m_cache.begin(); it != m_cache.end();++it )

    {

       if( (*it)->getId() == id)

          return *it;

    }

   

    returnNULL;

}


void BBFactoryCell::moveObject( BBDataCell* data ,int position )

{

   BBFactoryArray::iterator it = find(m_cache.begin(), m_cache.end(),data);

   

    if( it !=m_cache.end() )

    {

       m_cache.erase(it);

       

       if( position <m_cache.size() )

          m_cache.insert(m_cache.begin() + position,data);

       else

          m_cache.push_back(data);

    }

}


bool BBFactoryCell::saveData()

{

    BBDataCell*cell = NULL;

   BBFACTORY_FOREACH( this, cell )

    {

       BBDataCell *dataCell =(BBDataCell*)cell;

       

       if( dataCell )

       {

          dataCell->saveData();

       }

    }


    returntrue;

}


void BBFactoryCell::readData( sqlite3_stmt *stm)

{


}

cocos2dxの内存管理

Cocos2dx的内存管理是以引用计数的方式  

C++中指针的内存申请与释放问题


除了内置类型,只要有new必须有delete

局部变量类型在函数结束时释放

成员变量在对象释放时释放


C++中指针在new和delete操作时的动作

1 指针的new操作 

  指针在new之后,会在内存对中分配一个空间,而指针中存放的就是这个空间的地址。

2 指针的delete操作

指针在delete的时候,会将指针指向的内存区域释放掉,而指针同内存区域的联系并没有被切断,

任然会指向原来指向的内存区域。

3空指针指向的内存区域为内存的首地址,是不可读写的区域,即空指针不提供操作。删除空指针是安全的。所以在写构造函数,赋值操作符,或其他成员函数时,类的每个指针成员要么指向有效内存,要么指向空,那在你的析构函数里你就可以只用简单的delete掉他们,而不用担心他们是不是被new过。

程序崩溃的大部分问题都是内存释放问题

关注对象的释放即可解决大部分程序崩溃问题

CCScrollLayerExt  CCListViewCCTableView 列表控件

消息监听控件(变量监听控件)

网络回调控件

Cocos2dx 关于CCNotificationCenter的封装


BBNotificationCenter


#ifndef XXQX_BBNotificationCenter_h

#define XXQX_BBNotificationCenter_h


#include "BBMainMacros.h"

#include "CCNotificationCenter.h"

#include


class BBNotificationCenter : public CCObject

{

public:

   BBNotificationCenter();

   ~BBNotificationCenter();

   

    staticBBNotificationCenter *sharedNotifCenter(void);

    static voidpurgeNotifCenter(void);

   

    voidaddObserver(CCObject *target,

                 SEL_CallFuncO selector,

                  const char*name,

                  CCObject*obj);

   

    voidremoveObserver(CCObject *target,const char *name);

   

   

    voidregisterScriptObserver(int handler);

   

   

    voidunregisterScriptObserver(void);

   

    voidpostNotification(const char *name);

    voidpostNotification(const char *name, CCObject *object);

   

   

    inline intgetScriptHandler() { return m_scriptHandler; };

private:

    //

    // internalfunctions

    //

    boolobserverExisted(CCObject *target,const char *name);

   

    //

    //variables

    //

    map<string, CCNotificationObserver*> m_observers;

   

    int    m_scriptHandler;

   

    unsigned intm_uCount;

};


#endif

#include "BBNotificationCenter.h"

#include "CCScriptSupport.h"

static BBNotificationCenter *s_sharedNotifCenter =NULL;

BBNotificationCenter::BBNotificationCenter()

{

    m_uCount =0;

}


BBNotificationCenter::~BBNotificationCenter()

{

   m_observers.clear();

}


BBNotificationCenter*BBNotificationCenter::sharedNotifCenter(void)

{

    if(!s_sharedNotifCenter)

    {

       s_sharedNotifCenter = newBBNotificationCenter;

    }

    returns_sharedNotifCenter;

}


voidBBNotificationCenter::purgeNotifCenter(void)

{

   CC_SAFE_RELEASE_NULL(s_sharedNotifCenter);

}




//

// internal functions

//

bool BBNotificationCenter::observerExisted(CCObject*target,const char *name)

{

    if(m_observers.count(name) )

    {

       map< string,CCNotificationObserver*>::iterator it =m_observers.find(name);

       

       for( int i = 0; i <m_observers.count(name); ++i )

       {

          if( it->second->getTarget() == target)

              returntrue;

          

          //it++;

       }

    }

   

    returnfalse;

}

//

// observer functions

//

void BBNotificationCenter::addObserver(CCObject*target,

                                SEL_CallFuncO selector,

                                 const char*name,

                                 CCObject*obj)

{

    if(this->observerExisted(target, name))

       return;

   

   CCNotificationObserver *observer = NULL;

   

    observer = newCCNotificationObserver(target, selector, name, obj);

   

    if ( observer== NULL) {

       delete observer;

       return;

    }

   

    if(!m_observers.insert( pair(name, observer)).second )

    {

       

       for( map::iterator it =m_observers.begin(); it != m_observers.end(); ++it )

       {

          BBOUT<<it->first<<endl;

       }

       

       return ;

       

       //CCAssert(0, "Inser observererror !");

    }

   

   m_uCount++;

}


void BBNotificationCenter::removeObserver(CCObject*target,const char *name)

{

    if(m_observers.count(name) )

    {

       map< string,CCNotificationObserver*>::iterator it =m_observers.find(name);

       

       for( int i = 0; i <m_observers.count(name); ++i )

       {

          if( it->second->getTarget() == target)

          {

             it->second->release();

             m_observers.erase(it);

             m_uCount--;

              return;

          }

       }

    }

    else

    {

      BBOUT<<"BBNotificationCenter removeObserver not found!"<<endl;

    }

}


voidBBNotificationCenter::registerScriptObserver(int handler)

{

   unregisterScriptObserver();

   m_scriptHandler = handler;

}




voidBBNotificationCenter::unregisterScriptObserver(void)

{

    if(m_scriptHandler)

    {

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

      ((CCScriptEngineProtocol*)CCScriptEngineManager::sharedManager()->getScriptEngine())->removeScriptHandler(m_scriptHandler);

#endif

    }

   m_scriptHandler = 0;

}




void BBNotificationCenter::postNotification(constchar *name, CCObject *object)

{

    if(m_observers.count(name) )

    {

      BBOUT<<m_observers.count(name)<<endl;

       

       map< string,CCNotificationObserver*>::iterator it =m_observers.find(name);

       

      (it->second)->performSelector(object);

    }

}


void BBNotificationCenter::postNotification(constchar *name)

{

   this->postNotification(name,NULL);

}



————————————————————————————————————————————————————————————————————————————————————————

OC 基础语法

C++xml解析库 tinyxml 

C字符串处理函数(主要)

strlen(const char[]) 计算测试字符串的长度,不包括'\0'在内

sizeof(const char[]) 计算字节数  

asio 准C++标准库 

c++标准库 boost的asio异步网络库,非常方便,很容易实现网络传输。

asio库支持TCP/UDP/ICMP通信协议,它在名字空间boost::asio::ip里提供了大量网络通信方面的函数和类,很好地封装了原始的BerkeleySocket API,展现给asio用户一个方便易用且健壮的网络通信库。

单例模式保证类有且仅有一个实利,并且提供一个全局的访问点,通常的全局变量技术虽然也可以提供类似的功能,但它不能防止用户创建多个实例。

编程经验:

使用良好的编程风格,不要吝啬空格、空行,总是用TAB缩进,为变量、函数、类起个好名字,勤加注释,让代码更容易阅读和维护。

尽量找出最简单实现功能的办法,使代码尽量简单。

善用开源库,如果在开发中遇到什么问题,先从STL/Boost中寻找,如果不能解决再用因特网搜索,最后才自己动手解决

不能仅了解一门编程语言,这样很容易僵化解决问题的思路,在精通C++之余也应该多了解一下其他语言的发展和知识,可以开阔视野,从而更好地发现C++的优点和不足。

方法学很重要,应该书序编程语言之上的各种开发范式,如设计模式、重构技术、UML建模、敏捷开发、极限编程等

使用好的开发工具,易用的、效率高的开发工具可以节约大量的时间,

boost::asio 网络编程例子 

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html

怎样在xcode里面使用Memory Leaks和Instruments教程【检测内存泄露】

lua脚本基础语法

在lua中具有一个代码块的概念,每个函数或者for循环等都是一个代码块,在乱中,用--来标记该行注释“--[[”和“--]]”之间括起来的部分进行块注释。

lua中支持的算术运算符有:+ - * / == ~= < > <=>= 

lua中支持的逻辑运算符有:and or not 

基本数据类型:

lua中具有5中基本的数据类型,nil Boolean string Numbertable 在lua中使用变量不需要提前声明,变量的类型决定于用户赋值的类型,可以使用type()函数判断变量的类型,其中,nil、BooleanNumber都是用法比较简单的类型,stringtable类型用法稍微复杂点,给一个变量赋值为nil,表示释放该变量,Boolean跟其他语言一样,只有true和false两种值,Number是双精度浮点数,lua中没有整数类型,table类型可以当做数组使用,注意:在lua中,变量默认是全局的,这通常导致一些调试困难,最好尽量显式的在变量名之前加上local关键字声明该变量为局部变量。

string和table两种类型的详细用法

string类型的用法

  lua中字符串操作非常出色

字符于数字的显式转换

print(tonumber("100")+11) - -111

print(type(tostring(100)))--string

常用字符处理函数介绍

lua中的常用语句结构以及函数

lua中常用语句结构介绍

lua中的函数

 在lua脚本中,函数是function关键字开始,然后是函数名称,参数列表,最后以end关键字表示函数结束。需要注意的是,函数中的参数是局部变量,如果参数列表中存在(…)时,lua内部将创建一个类型为table的局部变量arg,用来保存所有调用时传递的参数及参数的个数(arg.n)

lua函数的返回值跟其他语言比较的话,特殊的是能够返回多个返回值return之后,该lua函数从lua的堆栈里被清理

lua中的库函数

lua中常用的库函数

lua与C++交互

lua与C/C++交互,主要是靠luaAPI和向lua注册好的函数。

lua调用C函数时,并不依赖于函数名,包的位置或可见性规则,而只依赖于注册时传入的函数地址。

在lua中如何调用C/C++函数

1 往lua中注册函数指针,并告诉lua该函数有几个参数,几个返回值

2 在lua中调用C/C++注册的函数

3 在C/C++函数中,从栈中一次弹出参数,然后进行处理,最后将返回值压入栈中

lua http://book.luaer.cn/

出栈  入栈  

Cocos2d-x是基于引用计数来管理内存的,应用计数的加减就是retain和release方法的实现,在大多数情况下我们不用显示的区调用这两种方法,如CCNode何addChild和removeChild方法,CCArray的addObject和removeObject等这样成双成对的方法。

深入理解Cocos2d-x内存管理

内联函数

在内联函数里不允许使用循环语句和开关语句

内联函数的定义必须出现在内联函数第一次调用之前

类型强转 将传入时是基类的对象指针强转成派生类的对象指针,调用派生类的成员函数。

lua中表的使用

关系表类型

基本介绍 所有元素之间,总是用逗号隔开

所有索引值都需要用[]括起来,如果是字符串还可以去掉引号和中括号,

编程思维的培养

游戏SDK接入流程

PP 

分享SDK接入流程

腾讯微博

oc学习记录


iphone操作系统

Cocoa Touch:提供触摸功能

Media 提供媒体功能

Core Services 核心服务

Core OS 操作系统的内核

参数说明关键字    

OC的特殊数据类型

id类型 BOOL nil SEL YES NO 

SEL是selector的一个类型,代表一个方法,等同于C语言中的函数指针

OC中的内存管理也是利用引用计数器原理

继承主要有以下几种典型的用法

代码复用 

创建协议类 

通用性能的发布

需要对现有逻辑进行轻微改动

功能预览

Obj-c中的类别和协议

Obj-C中的协议有些类似C++的纯函数,协议会定义一些列的方法,每个对象都可以对其进行引用,引用的同时必须实现协议里要求实现的方法,它不同于类和类别,类和类别的接口必须是实实在在存在的、特定的类里面才得以实现,而协议声明的接口则可以被任何类是吸纳,同时也可以被多个列实现。

Obj-C的属性 

指针参数是如何传递内存的?

如果函数的参数是一个指针,不要指望用该指针去申请动态内存,

编译器总要为函数的每个参数制作临时副本,指针参数p的副本是_p,编译器使_p =p,如果函数体内的程序修改了_p的内容,就导致参数p的内容做相应的修改,这就是指针可以用做输出参数的原因

*p

delete p;释放的是p所指向的内存空间

当容器中存放的是指针时,释放资源的时候必须首先逐个释放掉所指向的资源,然后才能删除容器,否则会造成资源泄露,尽量不要用vector存放指针,因为vector存储是拷贝,而对于指针来说,多一个备份就意味着多一份危险。

指针入门详解

其实指针就像是其他变量一样,所不同的是一般的变量包含的是实际的真实数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据。

LUA

什么样类型的函数可以被lua调用 

typedef int (*lua_CFunction)(lua_State *L);

符合类型的函数怎么样处理后才可以被lua调用

使用lua_register或者lua_pushfunction和lua_setglobal()把要调用的函数加入到lua状态机中。

Lua使用一个虚拟栈来和C传递值。栈上的每个元素都是一个Lua值(nil,数字,字符串等等)

无论何时lua调用C,被调用的函数都得到一个新栈,这个栈独立于C函数本身的堆栈,也独立于以前的栈(在C函数里,用luaAPI不能访问到lua状态机中本次调用之外的堆栈中的数据),它里面包含了lua传递给c函数所有的参数,而c函数则要把返回的结果也放入到堆栈以返回给调用者。

Lua使用C++中的类   调用方法

封装的大致流程

详解 

第三方库  

多版本问题 

为发行多版本

字号和字体大小尽量不要用json 尽量用宏控制

程序内不应直接出现文字性描述 

图片内不应直接出现文字性描述

尽量使用.string 和 .csv文件 

保存使用数据尽量用json等

多态  

面向对象语言中,接口的多种不同实现方式即为多态。

多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数

C++多态概念,允许父类指针或名称来引用子类对象或对象方法,而实际调用的方法为对象的类类型方法。多态性使得能够利用同一类(基类)类型的指针来引用不用类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。多态实现方法分为:基于继承和虚函数的动态多态和基于模板的静态多态。

C++设计模式 

工厂模式  

策略模式 

详解

工厂模式分为  简单工厂模式 工厂方法模式抽象工厂模式 

保存信息到内存文件(下次进入游戏再次使用)

使用结构体或字符串(最好是结构体)

结构体数组   然后用C++库保存  

模块的写法  

例子 :

苹果开发流程

xcode简介

网络通信范例

boost/asio

应用程序必须有一个io_service对象,io_service对象负责连接应用程序与操作系统的IO服务

在大多数语言中,对象的类型限制了对象可以执行的操作

左值 左值可以出现在赋值语句的左边或右边

右值 右值只能出现在赋值语句的右边,不能出现在赋值语句的左边。

变量的定义指定了变量的类型和标识符,也可以为对象提供初始值。

初始化指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替。

定义如何进行初始化的成员函数称为构造函数。

string 类型在标准库中定义 用于存储不同长度的字符串。

当定义没有初始化式的变量时,系统有时候会帮我们初始化变量。

C/C++文件读取操作总结

基于C的文件操作


1.fopen()

  fopen的原型是:FILE *fopen(const char *filename,const char*mode),fopen实现三个功能


为使用而打开一个流 

把一个文件和此流相连接 

给此流返回一个FILR指针

参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下表


字符串 含义 

"r" 以只读方式打开文件 

"w" 以只写方式打开文件 

"a" 以追加方式打开文件 

"r+" 以读/写方式打开文件,如无文件出错 

"w+" 以读/写方式打开文件,如无文件生成新文件 


  一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符''\n'',而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。


  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。


  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。


  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL。


例:


  FILE*fp; 

  if(fp=fopen("123.456","wb"))

    puts("打开文件成功");

  else 

    puts("打开文件成败"); 


2.fclose() 

  fclose()的功能就是关闭用fopen()打开的文件,其原型是:intfclose(FILE *fp);如果成功,返回0,失败返回EOF。


  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的毛病。


例:fclose(fp);


3.fputc()

  向流写一个字符,原型是int fputc(intc, FILE *stream); 成功返回这个字符,失败返回EOF。


例:fputc(''X'',fp);


4.fgetc()

  从流中读一个字符,原型是charfgetc(FILE *stream); 成功返回这个字符,失败返回EOF。


例:char ch1=fgetc(fp);


5. fseek()

  此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, intwhence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是


符号常量 值 基准位置 

SEEK_SET 0 文件开头 

SEEK_CUR 1 当前读写的位置 

SEEK_END 2 文件尾部 


例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)


  fseek(fp,0L,2);//把读写位置移动到文件尾


6.fputs()

  写一个字符串到流中,原型intfputs(const char *s, FILE *stream); 


例:fputs("I LoveYou",fp);


7.fgets()

  从流中读一行或指定个字符,原型是char *fgets(char*s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。


例:如果一个文件的当前位置的文本如下


Love ,I Have


But ……..


如果用


  fgets(str1,4,file1);


则执行后str1="Lov",读取了4-1=3个字符,而如果用


  fgets(str1,23,file1);


则执行str="Love ,IHave",读取了一行(不包括行尾的''\n'')。


8.fprintf()

  按格式输入到流,其原型是intfprintf(FILE *stream, const char *format[, argument,…]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了


例:fprintf(fp,"-%s",4,"Hahaha");


9.fscanf()

  从流中按格式读取,其原型是intfscanf(FILE *stream, const char *format[, address, …]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。


例:fscanf(fp,"%d%d",&x,&y);


10.feof()

  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE*stream);


例:if(feof(fp))printf("已到文件尾");


11.ferror()

  原型是int ferror(FILE*stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是voidclearerr(FILE *stream);


例:printf("%d",ferror(fp));


12.rewind()

  把当前的读写位置回到文件开始,原型是voidrewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);


例:rewind(fp);


12.remove()

  删除文件,原型是int remove(constchar *filename); 参数就是要删除的文件名,成功返回0。


例:remove("c:\\io.sys");


13.fread()

  从流中读指定个数的字符,原型是size_t fread(void*ptr, size_t size, size_t n, FILE*stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。


例:


  char x[4230];

  FILE*file1=fopen("c:\\msdos.sys","r");

  fread(x,200,12,file1);//共读取200*12=2400个字节


14.fwrite()

  与fread对应,向流中写指定的数据,原型是size_tfwrite(const void *ptr, size_t size, size_t n, FILE*stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int*等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。


例:


  char x[]="I LoveYou";

  fwire(x,6,12,fp);//写入6*12=72字节


  将把"I Love"写到流fp中12次,共72字节


15.tmpfile()

  其原型是FILE *tmpfile(void);生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。


例:FILE *fp=tmpfile();


16.tmpnam();

  其原型为char *tmpnam(char*s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。



基于C++的文件操作


在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:

1、插入器(<<)
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"WriteStdout"<<''\n'';就表示把字符串"WriteStdout"和换行字符(''\n'')输出到标准输出流。

2、析取器(>>)
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。

  在C++中,对文件的操作是通过stream的子类fstream(filestream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。

一、打开文件
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:

void open(const char* filename,int mode,int access);

参数:

filename:  要打开的文件名 
mode:    要打开文件的方式 
access:   打开文件的属性
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下: 

ios::app:   以追加的方式打开文件 
ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性 
ios::binary:  以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文 
ios::in:    文件以输入方式打开 
ios::out:   文件以输出方式打开 
ios::nocreate: 不建立文件,所以文件不存在时打开失败  
ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败 
ios::trunc:  如果文件存在,把文件长度设为0 
  可以用“或”把以上属性连接起来,如ios::out|ios::binary

  打开文件的属性取值是:

0:普通文件,打开访问 
1:只读文件 
2:隐含文件 
4:系统文件 
  可以用“或”或者“+”把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打开文件。

  例如:以二进制输入方式打开文件c:\config.sys 

  fstreamfile1;
  file1.open("c:\\config.sys",ios::binary|ios::in,0);

  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:

  file1.open("c:\\config.sys");<=>file1.open("c:\\config.sys",ios::in|ios::out,0);

  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:

  fstreamfile1("c:\\config.sys");

  特别提出的是,fstream有两个子类:ifstream(input filestream)和ofstream(outpu filestream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。

  ifstreamfile2("c:\\pdos.def");//以输入方式打开文件
  ofstreamfile3("c:\\x.123");//以输出方式打开文件

  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。

二、关闭文件
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。

三、读写文件
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式

  1、文本文件的读写
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:

  file2<<"I LoveYou";//向文件写入字符串"I LoveYou"
  intI;
  file1>>I;//从文件输入一个整数值。 

  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些

操纵符 功能 输入/输出 
dec 格式化为十进制数值数据 输入和输出 
endl 输出一个换行符并刷新此流 输出 
ends 输出一个空字符 输出 
hex 格式化为十六进制数值数据 输入和输出 
oct 格式化为八进制数值数据 输入和输出 
setpxecision(int p) 设置浮点数的精度位数 输出 

  比如要把123当作十六进制输出:file1<<hex<<123;要把3.1415926以5位精度输出:file1<<setpxecision(5)<<3.1415926。

  2、二进制文件的读写
①put()
  put()函数向流写入一个字符,其原型是ofstream&put(char ch),使用也比较简单,如file1.put(''c'');就是向流写一个字符''c''。 

②get()
  get()函数比较灵活,有3种常用的重载形式:

  一种就是和put()对应的形式:ifstream &get(char&ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。

  另一种重载形式的原型是: intget();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。

  还有一种形式的原型是:ifstream &get(char*buf,int num,char delim=''\n'');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符''\n''。例如:

  file2.get(str1,127,''A'');//从文件中读取字符到字符串str1,当遇到字符''A''或读取了127个字符时终止。

③读写数据块
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:

    read(unsigned char *buf,intnum);
    write(const unsigned char*buf,int num);

  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。

例:

    unsigned char str1[]="I LoveYou";
    intn[5];
    ifstreamin("xxx.xxx");
    ofstreamout("yyy.yyy");
    out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
    in.read((unsignedchar*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
    in.close();out.close(); 

四、检测EOF
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();
例:  if(in.eof())ShowMessage("已经到达文件尾!");

五、文件定位
  和C的文件操作方式不同的是,C++I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和 seekp(),seekg()是设置读位置,seekp是设置写位置。它们最通用的形式如下:

    istream &seekg(streamoffoffset,seek_dir origin);
    ostream&seekp(streamoff offset,seek_dirorigin); 

  streamoff定义于 iostream.h 中,定义有偏移量 offset所能取得的最大值,seek_dir表示移动的基准位置,是一个有以下值的枚举: 

ios::beg:  文件开头 
ios::cur:  文件当前位置 
ios::end:  文件结尾 
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。

例:

     file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节
     file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节 




了解:

基于WINAPI的文件操作

基于BCB库的文件操作

特殊文件操作

xcode 问题bug 如果工程每次都编译源文件  

可能是由于mac系统时间错误导致

http://blog.csdn.net/ryanzheng/article/details/27703331

有空的windows下可以配下环境试试。




\\192.168.7.15\Software\Windows\andriod环境编译



http://blog.csdn.net/langresser_king/article/details/8275291



defaults write com.apple.finder AppleShowAllFiles-bool true

mac下显示隐藏文件命令


当一张图片被加载到内存后,它是以纹理的形式存在的。纹理是什么东西,纹理就是一块内存,这块内存中存放的是按照指定的像素格式填充的图片像素信息,它被最终作为三角面着色所依据的数据源。

什么是回调函数

   模块A有一个函数foo,它向模块B传递foo的地址,然后在B里面发生某种事件时,通过从A里面传递过来的foo的地址调用foo,通知A发生了什么事情,让A做出相应反应,那么我们就把foo成为回调函数。


http://blog.xulingmin.com/ cocos2dx源码解释





本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C 语言之四 编译器(转)
C 知识点
指针与引用
C++经典面试题
详解C语言那些可怕的野指针
C++的参数传递机制[转]
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服