ObjC转换为cpp的规则

本文档详细介绍了从Objective-C到C++的转换规则,包括虚拟成员函数使用、成员变量访问级别设定、两阶段初始化、属性定义等核心概念。此外还提供了从Objective-C到C++转换时的具体注意事项。

原文地址: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Rules_of_translating_objc_to_cpp


1. 是否使用虚拟成员函数

1. 在申明cpp成员函数时最好不要使用“virtual”关键字;

2. 但是,请检查你申明的成员函数是否重写了父类的成员函数,如果重写了,请加上“virtual”;

3. 如果你是继承了父类的虚拟成员函数,那么一定要加上“virtual”。


2. 公有、私有、保护成员函数

1. 默认所有的成员函数是公有的;

2. 以下情况中的成员函数必须得申明成私有的:

      a. 这个函数是在.m文件中申明的;

      b. 这个函数前有“private”关键字。


3. 公有、私有、保护成员变量

1. 申明所有的成员变量为“protected”,没有第二选择。


4. 两个阶段初始化类

1. 如何做:

      a. 第一阶段:在构造函数里初始化所有成员变量,但不要在构造函数里做任何有关逻辑的初始化工作。

      b. 第二阶段:将有关逻辑的初始化工作写在“CMyClass *init(...)”函数里,如果初始化失败,返回NULL。

2. 为什么:

      a. 我们决定放弃C++中的try-catch异常处理机制。这样做是为了减少封装和二进制文件大小。

3. 什么时候:

      a. 并不是所有的类都必须实现两个阶段的初始化,只有那些需要做有关逻辑初始化的类需要。换句话说,在构造函数里做逻辑操作是不允许的,尤其是那些有可能返回错误的操作。    

4. 为调用者:

      a. 如果你调用的类有“bool init(...)”函数,在构造函数之后就需要立马调用它。

 1#define CCX_BREAK_IF(cond) if(cond) break;
 2#define CCX_SAFE_DELETE(p)  if(p) {delete (p); (p) = NULL;}
 3
 4// declaration
 5class CCar
 6{
 7public:
 8    CCar();
 9    bool    init();
10    virtual ~CCar();
11
12protected:
13    CEngine* m_pEngine;
14    bool     m_bStarted;
15    bool     m_bLocked;
16};
17
18// 1st-phase construction
19// only set the default value & alloc memory
20CCar::CCar()
21:m_pEngine(new CEngine)
22,m_bStarted(false)
23,m_bLocked(true)
24{
25    printf("CCar constructor\n");
26}
27
28// 2st-phase construction
29// do logical initialization
30bool CCar::init()
31{
32    bool bRet = false;
33
34    do
35    {
36        m_bLocked = false;
37
38        CCX_BREAK_IF( !m_pEngine );        // defensive
39        CCX_BREAK_IF( !m_pEngine->start() );    // logic
40
41        // success
42        bRet = true;
43
44    } while(0);
45
46    printf("CCar init\n");
47    return bRet;
48}
49
50// destruction
51CCar::~CCar()
52{
53    if (m_pEngine)
54    {
55        delete m_pEngine;
56        m_pEngine = NULL;
57    }
58
59    printf("CCar destructor\n");
60}
61
62// invoker
63int _tmain(int argc, _TCHAR* argv[])
64{
65    // in heap
66    CCar* pCar = new CCar;
67    if (!pCar->init())
68    {
69        CCX_SAFE_DELETE(pCar);
70    }
71
72    // in stack
73    CCar car;
74    if (!car.init())
75    {
76        // do sth.
77    }
78
79    return 0;
80}

5. ObjC中的属性

1/** CCX_PROPERTY_READONLY is used to declare a protected variable.
 2    We can use get method to read the variable.
 3    @param varType : the type of variable.
 4    @param varName : variable name.
 5    @param funName : "get + funName" is the name of the get method.
 6    @warning : The get method is a public virtual function, you should override it first.
 7            The variables and methods declared after CCX_PROPERTY_READONLY are all public.
 8            If you need protected or private, please declare.
 9*/
10#define CCX_PROPERTY_READONLY(varType, varName, funName)\
11    protected: varType varName;\
12    public: virtual varType get##funName(void);
13
14/** CCX_PROPERTY is used to declare a protected variable.
15    We can use get method to read the variable, and use the set method to change the variable.
16    @param varType : the type of variable.
17    @param varName : variable name.
18    @param funName : "get + funName" is the name of the get method.
19                     "set + funName" is the name of the set method.
20    @warning : The get and set methods are public virtual functions, you should override them first.
21            The variables and methods declared after CCX_PROPERTY are all public.
22            If you need protected or private, please declare.
23*/
24#define CCX_PROPERTY(varType, varName, funName)\
25    protected: varType varName;\
26    public: virtual varType get##funName(void);\
27    public: virtual void set##funName(varType var);
28
29/** CCX_SYNTHESIZE_READONLY is used to declare a protected variable.
30    We can use get method to read the variable.
31    @param varType : the type of variable.
32    @param varName : variable name.
33    @param funName : "get + funName" is the name of the get method.
34    @warning : The get method is a public inline function.
35            The variables and methods declared after CCX_SYNTHESIZE_READONLY are all public.
36            If you need protected or private, please declare.
37*/
38#define CCX_SYNTHESIZE_READONLY(varType, varName, funName)\
39    protected: varType varName;\
40    public: inline varType get##funName(void){ return varName; }
41
42/** CCX_SYNTHESIZE is used to declare a protected variable.
43    We can use get method to read the variable, and use the set method to change the variable.
44    @param varType : the type of variable.
45    @param varName : variable name.
46    @param funName : "get + funName" is the name of the get method.
47                     "set + funName" is the name of the set method.
48    @warning : The get and set methods are public  inline functions.
49            The variables and methods declared after CCX_SYNTHESIZE are all public.
50            If you need protected or private, please declare.
51*/
52#define CCX_SYNTHESIZE(varType, varName, funName)\
53    protected: varType varName;\
54    public: inline varType get##funName(void){ return varName; }\
55    public: inline void set##funName(varType var){ varName = var; }

6. id

在objc中有些函数返回id,在cpp中应返回bool。在objc中你可以写[[[MyClass alloc] init] autorelease],因为你不用担心init函数会执行失败并返回nil,因为[nil autorelease]不会引起程序崩溃。但是在cpp中,我们返回bool,为了防止程序员这样写:pClass = (new MyClass())->init()->foo()。因为一旦init失败,会返回NULL,NULL->foo()会导致程序崩溃的。另外,如果foo()返回值不是MyClass*类型,比如返回bool,调用者将失去“new MyClass”指针,并无法在堆中删除它,这是很危险的。

@interface CTest
-(id) foo();

必须写成:

class CTest
{
    bool foo();
}


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

7. 其他建议

除了以上翻译的,我从http://cn.cocos2d-x.org/resource/show?nid=62摘取了部分转换的注意事项:

1. 不要使用C++里的__super来替代objc里的super。关键字__super仅能在VC++中被识别,但是无法被GCC给编译。因此你最好调用其父类名称,CCLayer::init()
2. 这里没有属性的概念。因此在objc里的属性,我们用get/set方法来代替。例如,如果你想要获取CCSprite的contentSize属性,你必须调用sprite->getContentSize()方法。contentSize的第一个字母应该为大写的“C”,之后为它加上“get”前缀。
3. 使用setter来设置属性的值,“player.position=…”,应变为player->setPosition(…)
4. 但是访问结构体的成员不遵循这一规则。例如,在winSize结构体中,没有“width”&“height”的getter/setter
5. 你不需要像objc那样,解释每一个参数的用途。例如,[CCSprite spriteWithFile…, rect…];直接转换为CCSprite::spriteWithFile(…, ….);
6. 我们已经完成了一些常用的CGGeometry函数,诸如CGRectMake, CGPointMake, CGSizeMake, CGPointZero, CGSizeZero, CGRectZero。你可以在cocos2dx/include/CCGemoetry.h中找到它们。它们的用途和iOS一样。仅有一点点不同在于它们的前缀,为了避免命名上的冲突,在cocos2d-x里,前缀为CG、NS、UI的类都统一改成了CC前缀。
7. 所有cocos2d-x里的游戏元素,例如sprite、layer、scene、label、action都在heap里被分配了内存。因此我们必须用指针“->”来调用它们的方法。
8. 在cpp里,用关键字“this”来代替objc里的“self”
9. 现在init方法的返回值是“bool”类型了。在cpp里没有关键字“id”,因此那些返回值为“id”的方法要么替换成对象的指针,要么换成bool。
10. 对于Android,由于标题栏占用了一些空间,因此你需要在cpp里这样设置玩家的位置(player.contenSize.width/2 + 40, winSize.height/2)。

11. 在c++里继承默认为private继承,因此需要在CCLayerColor类声明前加上“public”。
12. Cocos2d-iphone的主要作者RicardoQuesada建议我们在cocos2d-x中使用命名空间。检查你所调用的cocos2d-x类是在“cocos2d”命名空间还是在“CocosDenshion”命名空间是非常重要的。


还有一个偷懒的办法:objc到cpp的转换脚本

https://github.com/Deepscorn/c2d-to-x/downloads


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值