3

私は本(iPhone 3D Programming)のチュートリアルに従っています:

  • Objective-C ヘッダーおよびソース ファイル (ファイル拡張子はそれぞれ .h、.m -)、
  • Objective-C++ のヘッダー ファイルとソース ファイル (ファイル拡張子はそれぞれ .h、.mm)
  • C++ ヘッダーとソース ファイル (ファイル拡張子はそれぞれ .hpp、.mpp -)

正常にコンパイルされるサンプル Xcode プロジェクトが含まれています

サンプル プロジェクトを見つける前に、本からコードを手動で入力しましたが、以下に詳述するファイルに対して次のコンパイル エラーが発生していました。

  1. 不明なタイプ名「仮想」
  2. 予期されるメンバー名または ';' 宣言指定子の後

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. タイプ「IRenderingEngine」を参照するには、「struct」タグを使用する必要があります

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 File Inspector で想定されるファイル タイプにデフォルト設定されているため、ビルド設定で正しく動作するはずでした - Apple LLVM コンパイラ 4.2 - 言語 - 「コンパイル ソース = ファイル タイプに従って」 -これは、正常にコンパイルされるサンプル プロジェクトのビルド設定と同じです。

なんらかの奇妙な理由で、手動で作成したプロジェクトでビルド設定を「Compile Sources As = Objective-C++」に変更すると、コンパイル エラーが削除され、アプリケーションが期待どおりに実行されました。

一見同一の (ソースコードに関して) プロジェクト間でこの設定が一貫していない理由について、誰かが理由を提供できますか?

4

2 に答える 2

10

ヘッダー ファイルはコンパイルされません。ヘッダー ファイルは、プリプロセッサによって使用されます。#includeまたは#import元のテキストの実際のテキストは、元のテキストにコピー アンド ペーストしたかのように扱われます。

したがって、ファイルの名前が .hpp、.h、またはその他であるかどうかは問題ではありません。.m ファイルが .hpp ファイルを含む .h ファイルをインポートする場合、.hpp コードは .m ファイルの一部として、つまり Objective-C としてコンパイルされます。

したがって、私はあなたが持っていると推測しますGLView.m。直接または間接的に .hpp ファイルをインポートする場合は、Objective-C++ としてコンパイルする必要があります。これを行う 1 つの方法は、名前を .mm に変更することです。もう 1 つは、ファイル拡張子から言語の種類を推測しないようにプロジェクトに指示することです。

于 2013-07-31T22:35:19.690 に答える
3

GLView.hTommy と HotLicks は、差し迫った問題に対する正しい答えを提供してくれました。インクルードするすべてのソース ファイルが Objective-C ファイルであることを確認する必要があります.mm

ただし、これに別の側面を追加したいと思います。すべてのファイルをやみくもに Objective-C++ にするのは、悪い解決策です。C++ の機能を使用していないのに、なぜこれらすべてのファイルが Objective-C++ である必要があるのでしょうか? 答えは、それらがインポートすることGLView.hであり、GLViewクラスには、型が C++ 機能を含む構造体へのポインターであるインスタンス変数が含まれます。これらの他のファイルがそれを気にするのはなぜですか? 彼らはすべきではありません。

それについてあなたができることはさまざまです。

  • IRenderingEngineで前方宣言できますGLView.hIRenderingEngine.hppヘッダーは の内部構造を気にしないため、インポートする必要はありませんIRenderingEngine。それへのポインターを持つためには、それが何らかの型であることを知る必要があるだけです。これには前方宣言で十分です。(ただしstruct IRenderingEngine* m_renderingEngine;、C と互換性があるように記述する必要があります。)

  • さらに、GLViewクラスのインスタンス変数は、そもそもヘッダーで宣言する必要はありません。インスタンス変数は、代わりに実装 ( .m) ファイルの「クラス拡張」 (つまり@interface GLView () { ... }) で宣言するか、Xcode の新しいバージョンではクラス実装 ( @implementation GLView { ... })で直接宣言できます。

于 2013-08-03T20:02:47.060 に答える