oF (C++)でクラス二重定義してるぞと言われないために
June 04, 2014【注意】
- 古いブログの記事 “oF (C++)でクラス二重定義してるぞと言われないために - think with code” から移行したものです。
- 投稿日時表記は当時のままになっています。
openFrameworksをガリガリ書いているんですが,
C++でクラスをファイル分けして書いていると,ヘッダファイルを二重インクルードしてしまいビルドが通らないなんてことがあります.
具体的に書くと
- A.h:
class hoge{}
- B.h:
#include A.h
- C.h:
#include A.h , #include B.h
こんな状態.C.hにはA.hが二度インクルードされちゃって,_hoge_クラスが二重定義になっているのでこのままだとエラーが出ます.
この様なエラーを解決する方法が二つあるのでそれに関して書きます.
#ifndef
#define
#endif
Xcode ver.5.1.1 で新しくC++ファイルを作成すると,一緒にヘッダファイルも作成されるんですが,デフォルトだと中身がこんな感じになってます.(例えばtestClass.hだと)
#ifndef __testClass__testClass__
#define __testClass__testClass__
#include <iostream>
//ここにクラス定義等を記述
#endif /* defined(__testClass__testClass__) */
この中の#ifndef
#define
#endif
がその二重インクルードによる二重定義を解決してくれます.
どう解決してくれるかというと,これらはC++のソースをコンパイルする前にソースに前処理をする「プリプロセッサ」に関するの記述で,
- もし
#define hoge
されていたら, #ifndef hoge
~#endif hoge
内はスキップする
という処理をしてくれます. この記述方法をインクルードガードと呼ぶそうです.便利ですね.
ただしこれより簡単な記述で同じような処理をしてくれるものがあります.
#pragma once
それが#pragma once
というコマンド(?と呼べば良いのか)です.
openFrameworks ver.0.8.1 に含まれている_projectGenerator.app_で「testProject」というプロジェクトを作成すると,src
フォルダの中に
main.cpp
ofApp.cpp
ofApp.h
というファイルが作成されるんですが,ofApp.h
の中身を覗いてみると,
#pragma once
#include "ofMain.h"
class ofApp : public ofBaseApp{
...
というように,ファイルの冒頭に#pragma once
という記述があります.
この記述がインクルードガードと同じ働きをしするんですね.もし二重にインクルードされた場合には呼び出しを無視して中身をスキップしてくれます.便利です.
技術書とかリファレンス読むの大事だな
#pragma once
は新しいコンパイラでないと対応していないため,上記二つを併記するという裏技も存在するようです.
最新バージョンのXcodeとopenFrameworksを使っているなら気にしなくても良いですね.
どの言語に関しても言えることですが,知らない人が書いたブログ上のコードをコピペして勉強するだけじゃ気づかないこと知らないまま過ごしてしまうことが多いので,本を呼んで順序よく体系立てて学ぶのは時間かかる反面理解が深まるし深く定着するので良いです.