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

use*_*366 4 c++ iphone xcode objective-c

我最近开始学习编程,在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
Run Code Online (Sandbox Code Playgroud)

和相应的.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
Run Code Online (Sandbox Code Playgroud)

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

非常感谢!

Alf*_*nso 10

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

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

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

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

  • 当然不客气:-) 请注意:如果您需要仅在 Mac OS X 上运行的代码,您仍然可以在 C++ 代码中使用 NS* 类(它实际上是 Objective-C++ 代码,但这是由静默处理的)编译器)。当我提到摆脱 NS* 类时,我指的是问题的“将代码移植到另一个平台”部分。 (2认同)

dre*_*lax 8

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

  1. 没有@encode()编译器指令(用于NSValue和其他一些类).
  2. 没有直接的等同于doesNotRecognizeSelector:,respondsToSelector:,conformsToProtocol:performSelector:(类似性质的和其他方法).
  3. 在Objective-C中,可以发送消息nil,但在C++中,在空指针上调用成员函数是不行的.
  4. Objective-C允许使用类类别扩展现有类,例如,您可以添加一个NSString计算空间数的方法,该方法被调用numberOfSpaces,并且它将可用于NSString应用程序中的所有实例.
  5. C++不具有finally用于块try/ catch,但目标C具有@finally@try/ @catch.

如果您计划将应用程序发布到多个平台,那么您可以尝试尽可能多地抽象到单独的库中.您的iPhone应用程序可以使用Objective-C编写并使用库中的函数,如果您计划将其移植到其框架需要C++的另一个系统,那么您可以编写C++应用程序并使用相同库中的相同函数.我想你的图书馆基本上都是[至少]你的绘图程序和核心游戏引擎逻辑.