宏的单行定义
#define maxi(a,b) (a>;b?a:b)
宏的多行定义
宏可以替代多行的代码 关键是要在每一个换行的时候加上一个 "\ "
宏定义写出swap(x,y)交换函数
#define swap(x, y)\
x = x + y;\
y = x - y;\
x = x - y;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef __CC_PLATFORM_MACROS_H__
#define __CC_PLATFORM_MACROS_H__
/**
* define some platform specific macros //定义一些平台上特定的宏
*/
#include "ccConfig.h"
#include "CCPlatformConfig.h"
#include "CCPlatformDefine.h"
/**
* define a create function for a specific type, such as CCLayer
* @__TYPE__ class type to add create(), such as CCLayer
*/
#define CREATE_FUNC(__TYPE__) \ //创建参数类型实例 返回其指针 内部实现 1、调用实例init 2、将实例放入自动释放池
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \ //要求参数类内有init()
{ \
pRet->autorelease(); \ //要求参数类内有autorelease()
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
/**
* define a node function for a specific type, such as CCLayer
* @__TYPE__ class type to add node(), such as CCLayer
* @deprecated: This interface will be deprecated(弃用) sooner or later.
*/
#define NODE_FUNC(__TYPE__) \
CC_DEPRECATED_ATTRIBUTE static __TYPE__* node() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
/** @def CC_ENABLE_CACHE_TEXTURE_DATA //
Enable it if you want to cache the texture data.
Basically, it's only enabled for Emscripten.
It's new in cocos2d-x since v0.99.5
*/
#if (CC_TARGET_PLATFORM == CC_PLATFORM_EMSCRIPTEN)
#define CC_ENABLE_CACHE_TEXTURE_DATA 1
#else
#define CC_ENABLE_CACHE_TEXTURE_DATA 0
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_EMSCRIPTEN)
/* Application will crash in glDrawElements function on some win32 computers and some android devices.
Indices should be bound again while drawing to avoid this bug.
*/
#define CC_REBIND_INDICES_BUFFER 1
#else
#define CC_REBIND_INDICES_BUFFER 0
#endif
// generic macros 一般的宏
// namespace cocos2d {} //命名空间的宏定义 NS_CC_BEGIN NS_CC_END USING_NS_CC
#ifdef __cplusplus
#define NS_CC_BEGIN namespace cocos2d {
#define NS_CC_END }
#define USING_NS_CC using namespace cocos2d
#else
#define NS_CC_BEGIN
#define NS_CC_END
#define USING_NS_CC
#endif
/** CC_PROPERTY_READONLY is used to declare(宣布,声明) a protected variable. // ->cocos2d/cocos2d 属性
We can use getter to read the variable.
@param varType : the type of variable.
@param varName : variable name.
@param funName : "get + funName" is the name of the getter.
@warning : The getter is a public virtual function, you should rewrite it first.
The variables and methods declared after CC_PROPERTY_READONLY are all public.
If you need protected or private, please declare.
*/
#define CC_PROPERTY_READONLY(varType, varName, funName)\
protected: varType varName;\
public: virtual varType get##funName(void);
#define CC_PROPERTY_READONLY_PASS_BY_REF(varType, varName, funName)\
protected: varType varName;\
public: virtual const varType& get##funName(void);
/** CC_PROPERTY is used to declare a protected variable.
We can use getter to read the variable, and use the setter to change the variable.
@param varType : the type of variable.
@param varName : variable name.
@param funName : "get + funName" is the name of the getter.
"set + funName" is the name of the setter.
@warning : The getter and setter are public virtual functions, you should rewrite them first.
The variables and methods declared after CC_PROPERTY are all public.
If you need protected or private, please declare.
*/
#define CC_PROPERTY(varType, varName, funName)\
protected: varType varName;\
public: virtual varType get##funName(void);\
public: virtual void set##funName(varType var);
#define CC_PROPERTY_PASS_BY_REF(varType, varName, funName)\
protected: varType varName;\
public: virtual const varType& get##funName(void);\
public: virtual void set##funName(const varType& var);
/** CC_SYNTHESIZE_READONLY is used to declare a protected variable.
We can use getter to read the variable.
@param varType : the type of variable.
@param varName : variable name.
@param funName : "get + funName" is the name of the getter.
@warning : The getter is a public inline function.
The variables and methods declared after CC_SYNTHESIZE_READONLY are all public.
If you need protected or private, please declare.
*/
#define CC_SYNTHESIZE_READONLY(varType, varName, funName)\
protected: varType varName;\
public: virtual varType get##funName(void) const { return varName; }
#define CC_SYNTHESIZE_READONLY_PASS_BY_REF(varType, varName, funName)\
protected: varType varName;\
public: virtual const varType& get##funName(void) const { return varName; }
/** CC_SYNTHESIZE is used to declare a protected variable.
We can use getter to read the variable, and use the setter to change the variable.
@param varType : the type of variable.
@param varName : variable name.
@param funName : "get + funName" is the name of the getter.
"set + funName" is the name of the setter.
@warning : The getter and setter are public inline functions.
The variables and methods declared after CC_SYNTHESIZE are all public.
If you need protected or private, please declare.
*/
#define CC_SYNTHESIZE(varType, varName, funName)\
protected: varType varName;\
public: virtual varType get##funName(void) const { return varName; }\
public: virtual void set##funName(varType var){ varName = var; }
#define CC_SYNTHESIZE_PASS_BY_REF(varType, varName, funName)\
protected: varType varName;\
public: virtual const varType& get##funName(void) const { return varName; }\
public: virtual void set##funName(const varType& var){ varName = var; }
#define CC_SYNTHESIZE_RETAIN(varType, varName, funName) \
private: varType varName; \
public: virtual varType get##funName(void) const { return varName; } \
public: virtual void set##funName(varType var) \
{ \
if (varName != var) \
{ \
CC_SAFE_RETAIN(var); \
CC_SAFE_RELEASE(varName); \
varName = var; \
} \
}
///////////
宏定义中的do...while(0)
如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false), 比如说:
#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal); __analysis_assume(__afx_condVal); } while(0)
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do...while(0)有什么意义呢?
当然有!
为了看起来更清晰,这里用一个简单点的宏来演示:
#define SAFE_DELETE(p) do{ delete p; p = NULL} while(0)
假设这里去掉do...while(0),
#define SAFE_DELETE(p) delete p; p = NULL;
那么以下代码:
if(NULL != p) SAFE_DELETE(p)
else ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while, 我直接用{}括起来就可以了
#define SAFE_DELETE(p) { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) SAFE_DELETE(p);
else ...do sth...
其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择了。
也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就不需要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。
//所谓safe 仅仅是多了一个对参数的判断 如果不想记这些宏可以自己写
#define CC_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)
#define CC_SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = 0; } } while(0)
#define CC_SAFE_FREE(p) do { if(p) { free(p); (p) = 0; } } while(0)
#define CC_SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0)
#define CC_SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = 0; } } while(0)
#define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0)
#define CC_BREAK_IF(cond) if(cond) break
#define __CCLOGWITHFUNCTION(s, ...) \
CCLog("%s : %s",__FUNCTION__, CCString::createWithFormat(s, ##__VA_ARGS__)->getCString())
// cocos2d debug
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
#define CCLOG(...) do {} while (0)
#define CCLOGINFO(...) do {} while (0)
#define CCLOGERROR(...) do {} while (0)
#define CCLOGWARN(...) do {} while (0)
#elif COCOS2D_DEBUG == 1
#define CCLOG(format, ...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGERROR(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGINFO(format,...) do {} while (0)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#elif COCOS2D_DEBUG > 1
#define CCLOG(format, ...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGERROR(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGINFO(format,...) cocos2d::CCLog(format, ##__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#endif // COCOS2D_DEBUG
// Lua engine debug
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0 || CC_LUA_ENGINE_DEBUG == 0
#define LUALOG(...)
#else
#define LUALOG(format, ...) cocos2d::CCLog(format, ##__VA_ARGS__)
#endif // Lua engine debug
#if defined(__GNUC__) && ((__GNUC__ >= 5) || ((__GNUG__ == 4) && (__GNUC_MINOR__ >= 4))) \
|| (defined(__clang__) && (__clang_major__ >= 3))
#define CC_DISABLE_COPY(Class) \
private: \
Class(const Class &) = delete; \
Class &operator =(const Class &) = delete;
#else
#define CC_DISABLE_COPY(Class) \
private: \
Class(const Class &); \
Class &operator =(const Class &);
#endif
/*
* only certain compilers support __attribute__((deprecated))
*/
#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
#define CC_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
#elif _MSC_VER >= 1400 //vs 2005 or higher
#define CC_DEPRECATED_ATTRIBUTE __declspec(deprecated)
#else
#define CC_DEPRECATED_ATTRIBUTE
#endif
/*
* only certain compiler support __attribute__((format))
* formatPos - 1-based position of format string argument
* argPos - 1-based position of first format-dependent argument
*/
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define CC_FORMAT_PRINTF(formatPos, argPos) __attribute__((__format__(printf, formatPos, argPos)))
#elif defined(__has_attribute)
#if __has_attribute(format)
#define CC_FORMAT_PRINTF(formatPos, argPos) __attribute__((__format__(printf, formatPos, argPos)))
#endif // __has_attribute(format)
#else
#define CC_FORMAT_PRINTF(formatPos, argPos)
#endif
#if defined(_MSC_VER)
#define CC_FORMAT_PRINTF_SIZE_T "%08lX"
#else
#define CC_FORMAT_PRINTF_SIZE_T "%08zX"
#endif
#ifdef __GNUC__
#define CC_UNUSED __attribute__ ((unused))
#else
#define CC_UNUSED
#endif
#endif // __CC_PLATFORM_MACROS_H__