由于Xcode不符合文件类型,Objective-C ++编译错误

时间:2013-07-31 22:28:44

标签: xcode objective-c++

我正在阅读一本书中的教程(iPhone 3D Programming),该书使用:

  • Objective-C标头和源文件(文件扩展名分别为.h,.m),
  • Objective-C ++标头和源文件(文件扩展名分别为.h,.mm)
  • C ++标头和源文件(文件扩展名分别为.hpp,.mpp)

包含成功编译的sample Xcode project

在我找到示例项目之前,我已经手动输入了本书中的代码,但是我收到了以下详细文件的以下编译错误:

  1. 未知类型名称'virtual'
  2. 预期会员名称或';'在声明说明符之后
  3. IRenderingEngine.hpp(Xcode File Inspector - File Type =“Default - C ++ Header”)

    ...
    struct IRenderingEngine {
        virtual void Initialize(int width, int height) = 0; //2 errors as marked above
        virtual void Render() const = 0; //2 errors as marked above
        virtual void UpdateAnimation(float timeStep) = 0; //2 errors as marked above
        virtual void OnRotate(DeviceOrientation newOrientation) = 0; //2 errors as marked above
        virtual ~IRenderingEngine() {} //2 errors as marked above
    };
    ...
    
    1. 必须使用'struct'标签来引用'IRenderingEngine'类型
    2. GLView.h(Xcode File Inspector - File Type =“Default - C Header”)

      #import "IRenderingEngine.hpp"
      #import <QuartzCore/QuartzCore.h>
      
      @interface GLView : UIView {
      @private
          EAGLContext* m_context;
          IRenderingEngine* m_renderingEngine; //1 error marked above
          float m_timestamp;
      }
      
      - (void) drawView:(CADisplayLink*)displayLink;
      - (void) didRotate:(NSNotification*)notification;
      
      @end
      

      所有其他文件的文件类型也默认为Xcode文件检查器中的预期文件类型,因此应该可以正常使用构建设置 - Apple LLVM编译器4.2 - 语言 - “将源编译为=根据文件键入“ - 这与成功编译的示例项目中的构建设置相同。

      由于一些奇怪的原因,在我手动创建的项目中将Build Setting更改为“Compile Sources As = Objective-C ++”,删除了编译错误,应用程序按预期运行。

      任何人都可以提供一个理由,说明为什么这个设置在看似相同(源代码方面)的项目之间不一致吗?

2 个答案:

答案 0 :(得分:10)

未编译头文件。头文件由预处理器使用 - 只要您有#include#import,原始文本的实际文本就会被视为您将其复制并粘贴到原始文本中。

因此,如果您的文件被称为.hpp,.h或其他任何内容都无关紧要。如果.m文件导入包含.hpp文件的.h文件,则.hpp代码将被编译为.m文件的一部分,即作为Objective-C。

因此我猜你已经GLView.m了。如果要导入.hpp文件,无论是直接还是间接,都需要编译为Objective-C ++。一种方法是重命名.mm,另一种方法是告诉项目不要试图通过文件扩展名来猜测语言类型。

答案 1 :(得分:3)

Tommy和HotLicks为您提供了直接问题的正确答案 - 您需要确保包含GLView.h的所有源文件都是Objective-C文件,并命名为.mm

但是,我想为此添加另一面。盲目地制作所有文件Objective-C ++是一个糟糕的解决方案。它应该引导你问自己:为什么所有这些文件都需要是Objective-C ++,如果它们不使用C ++特性?答案是它们导入GLView.hGLView类包含一个实例变量,其类型是指向包含C ++特性的结构的指针。为什么这些其他文件关心这个?他们不应该。

你可以做很多事情。

  • IRenderingEngine可以在GLView.h中向前声明。无需导入IRenderingEngine.hpp,因为标题不关心IRenderingEngine的内部结构;它只需要知道它是某种类型,以便有一个指向它的指针。前言声明就足够了。 (但是,有必要写struct IRenderingEngine* m_renderingEngine;以与C兼容。)

  • 此外,GLView类的实例变量不需要首先在标题中声明。实例变量可以在实现(.m)文件中在“类扩展”(即@interface GLView () { ... })中声明,或者在较新版本的Xcode中直接在类实现中声明{{1 }})