#ifdef と #ifndef
http://blog.s21g.com/articles/1058
にあるとおり。簡潔。
静的ライブラリを作る練習(ちょー基本的)
- 作者: D. Ryan Stephens,Christopher Diggins,Jonathan Turkanis,Jeff Cogswell,株式会社クイープ
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2006/09/26
- メディア: 大型本
- 購入: 1人 クリック: 35回
- この商品を含むブログ (15件) を見る
"John, Paul, "
とだけ画面に出力する関数を定義した静的ライブラリを作る。中の処理はちょー簡単なんだけど、ファイルの組み合わせで静的ライブラリを作ってみようぜ!っていう練習なのでわざわざ細かくファイルが分割されてる。
構成
- john.cpp内で "John, "までを出力する関数を書き
- paul.cpp内で "Paul, "までを出力する関数を書く。
- johnpaul.cppで、上記二つの関数をつかって連続して"John, Paul, "と出力するようにする。
- 静的ライブラリlibjohnpaul.a としてまとめる。
john.hppとjohn.cppのソースはこんな感じ
/* john.hpp */ #ifndef JOHN_HPP_INCLUDED #define JOHN_HPP_INCLUDED void john(); //prints "John, " #endif /* john.cpp */ #include <iostream> #include "john.hpp" void john() { std::cout << "John, "; }
これと同内容のpaul.cpp/hppがあり、johnとpaulをまとめるのがjohnpaul.cpp
/* johnpaul.hpp */ #ifndef JOHNPAUL_HPP_INCLUDED #define JOHNPAUL_HPP_INCLUDED void johnpaul(); //Prints "John, Paul, " #endif /* johnpaul.cpp */ #include "john.hpp" #include "paul.hpp" #include "johnpaul.hpp" void johnpaul() { john(); paul(); }
誤って #ifdef を使うと
ここで僕は、すべてのヘッダファイル(.hpp)の、#ifndefのとこを、あやまって#ifdefと書いてしまった。
こうすると、#ifdef JOHN_HPP_INCLUDED の判定は常に0 なので、中の void john(); という関数の宣言は行われないことになる。そしてこのままでも john.cpp(およびpaul.cpp) のコンパイルは通る。main()の無い記述なので、宣言しなくても関数の定義だけは出来る。
しかし、johnpaul.cppはコンパイルエラーになる。#includeしたjohn.hpp と paul.hpp の宣言の部分が、#ifdef **_INCLUDED の判定により飛ばされてしまうため、
/* johnpaul.cpp */ #include "john.hpp" //void john(); の定義部はコンパイルされない #include "paul.hpp" //void paul(); の定義部はコンパイルされない #include "johnpaul.hpp" void johnpaul() { john(); //宣言されてない paul(); //宣言されてない }
の、john(); paul();関数が見つからないからだ。
ということがわかってよかった。よしよし。