将Objective C格式的代码转换为纯C ++

时间:2010-08-31 21:20:27

标签: c++ iphone objective-c xcode

我最近开始学习编程,在iPhone上制作我自己的3D OpenGL游戏,到目前为止已取得了相当不错的进展。我开始使用随iPhone SDK提供的基本OpenGL示例,这帮助我开始了一个良好的开端。然而,当我开始掌握一些事情时,我发现我在Objective C中进行了不必要的编程,这将使得将来将游戏移植到其他平台变得更加困难。所以我认为最好现在正确地使用C ++来避免以后的大量额外工作。

澄清一下:我实际上并没有使用任何对Apple(Objective C)函数或其他任何函数的调用,只是因为我将所有的条款都基于Objective C风格的init / dealloc / etc,所以我的引擎使用时看起来像Objective C类。我的目标是用C ++等价物替换所有目标C的东西...麻烦的是,对C ++来说还是新手,我不确定与什么相符!

这是我的一个类(myLight)的简单示例,在其当前的Objective C版本中:

//  myLight.h

#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>

@interface myLight : NSObject {
    char *name;
    GLfloat *ambient, *diffuse, *specular, *position, *spotDirection;
    GLfloat spotRadius;

    GLfloat *matAmbient, *matDiffuse, *matSpecular;
    GLfloat shininess;
    Byte lightType;
}
@property (readonly) char *name;
@property (assign) GLfloat *position;
@property (assign) GLfloat *spotDirection;

@property (assign) GLfloat *ambient;
@property (assign) GLfloat *diffuse;
@property (assign) GLfloat *specular;

- (id)initWithContentsFromDatastream:(NSData *)fileData;
- (void)set;

@end

和相应的.mm文件:

//  myLight.m

#import "myLight.h"

@implementation myLight
@synthesize name, ambient, diffuse, specular, position, spotDirection;

- (id)initWithContentsFromDatastream:(NSData *)fileData {
    self = [super init];
    NSData *fileContents = fileData;
    uint ptr = 0;

    Byte nameLength;
    [fileContents getBytes:&nameLength range: NSMakeRange(ptr, sizeof(Byte))];
    ptr++;

    name = new char[nameLength];
    [fileContents getBytes:name range: NSMakeRange(ptr, (nameLength * sizeof(char)) )];
    ptr = ptr + (nameLength * sizeof(char) );

    [fileContents getBytes:&lightType range: NSMakeRange(ptr, sizeof(Byte))];
    ptr++;

    position = new GLfloat[4];
    for(int j = 0; j < (4); j++)
        [fileContents getBytes:&position[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
    ptr = ptr + (4 * sizeof(float));

    if(lightType==2){
        spotDirection = new GLfloat[3];
        for(int j = 0; j < (3); j++)
            [fileContents getBytes:&spotDirection[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
        ptr = ptr + (3 * sizeof(float));

        [fileContents getBytes:&spotRadius range: NSMakeRange(ptr, sizeof(float))];
        ptr = ptr + sizeof(float);
    } else 
        spotDirection = NULL;

    diffuse = new GLfloat[4];
    for(int j = 0; j < (4); j++)
        [fileContents getBytes:&diffuse[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
    ptr = ptr + (4 * sizeof(float));

    ambient = new GLfloat[4];
    for(int j = 0; j < (4); j++)
        [fileContents getBytes:&ambient[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
    ptr = ptr + (4 * sizeof(float));

    specular = new GLfloat[4];
    for(int j = 0; j < (4); j++)
        [fileContents getBytes:&specular[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
    ptr = ptr + (4 * sizeof(float));

    [self set];

  return self;
}

- (void)set{
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
    glLightfv(GL_LIGHT0, GL_POSITION, position);

    if(lightType==2)
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection);
}

- (void)dealloc {
    delete[] specular;
    delete[] ambient;
    delete[] diffuse;

    if (spotDirection)
        delete[] spotDirection;

    delete[] position;
    delete[] name;

    [super dealloc];
}

@end

如果有人可以指出哪些行需要更改,更重要的是,应该将它们更改为使其编译为纯C ++,我真的很感激。

非常感谢!

2 个答案:

答案 0 :(得分:10)

首先,请记住,Objective-C不仅仅是C的“不同格式”,它是一种单独的语言,更重要的是,在Cocoa的情况下,一个单独的框架。因此,如果您希望将来能够将项目移植到其他平台,您不仅需要摆脱Objective-C,还需要摆脱Cocoa框架。

要将类从Objective-C映射到C ++,您必须执行以下操作:

  • 创建一个新的C ++类来替换旧类
  • -init...方法
  • 创建构造函数
  • -dealloc方法
  • 创建析构函数
  • 创建其他复制功能的方法
  • 对于您可能会创建getter和setter的属性
  • #import替换为#include指令,因为此指令仅存在于Objective-C中(确保您包含的标题受到多个包含的保护)
  • 摆脱NS ...类和方法的用法,因为它们是Cocoa框架的一部分,很可能无法移植

您应该花些时间考虑如何使用您正在撰写的代码。移植1:1可能不是一个好主意,因为在Cocoa和C ++(或任何其他语言/框架)中编码之间的习语存在很多差异。

答案 1 :(得分:8)

大多数应用程序逻辑可以翻译成C ++,但是在C ++中会有一些没有直接等价的东西。例如:

  1. 没有@encode()编译器指令(用于NSValue和其他一些类)。
  2. 没有简单的等同于doesNotRecognizeSelector:respondsToSelector:conformsToProtocol:performSelector:(和其他类似性质的方法)。
  3. 在Objective-C中,可以向nil发送消息,但在C ++中,在空指针上调用成员函数是不行的。
  4. Objective-C允许使用类类别扩展现有类,例如,您可以向NSString添加一个方法,该方法计算名为numberOfSpaces的空格数,并且它将可供所有NSString使用finally 1}}你的应用程序中的实例。
  5. C ++没有try / catch的{​​{1}}块,但Objective-C对@finally / @try@catch
  6. 如果您计划将应用程序发布到多个平台,那么您可以尝试尽可能多地抽象到一个单独的库中。您的iPhone应用程序可以使用Objective-C编写并使用库中的函数,如果您计划将其移植到其框架需要C ++的另一个系统,那么您可以编写C ++应用程序并使用相同库中的相同函数。我想你的图书馆基本上都是[至少]你的绘图程序和核心游戏引擎逻辑。