原文地址: 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”指针,并无法在堆中删除它,这是很危险的。
必须写成:
====================================================================================================================================
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
本文档详细介绍了从Objective-C到C++的转换规则,包括虚拟成员函数使用、成员变量访问级别设定、两阶段初始化、属性定义等核心概念。此外还提供了从Objective-C到C++转换时的具体注意事项。
192

被折叠的 条评论
为什么被折叠?



