いろきゅうの(元)はてなダイアリー

はてなダイアリーから移行中…

今日のハマったコード

クラスを作るとき、継承とかコンポジションするとかで、他のクラスに依存することが多々あります。こういう時は大抵…(相変わらずコードに深い意味はありません)
//-- A.h ------------
class A
{

};

//-- B.h ------------
#include "A.h"
class B
{
  A* m_pA;
};
というように、inlucdeしてカリカリ書いていくことになります。…が、クラス関係が複雑になるにつれ、ヘッダーでincludeしている点がネックになってきます。
仮に今回の場合、B.h が C.h と D.h というヘッダーファイルで inlucde されているとした場合、class A を弄くっただけで、A.cpp, B.cpp, C.cpp, D.cpp の4つのファイルを再コンパイルする必要性が出てきます。class C, class D には、直接的に class A の影響は無いのに…。 これでは時間が勿体無いです。
ので、上記のコードのように、あるクラスは違うクラスへのポインタだけが必要という場合は、こんな風に書いてます。

//-- A.h ---------------
class A {} ;

//-- B.h ---------------
class A; // 先行宣言
class B
{
  A* m_pA;
};

//-- B.cpp -------------
#include "A.h" // cppでヘッダをinlcude
void B::Func()
{
  m_pA->Func();
}

こうしておくと、class A のヘッダーを弄くったとしても、A.cpp, B.cpp だけの再コンパイルだけで済むので、さくっとコンパイルが終わります。

…が〜、ワナも待ち構えてたりしまして。^^;

//-- Base.h ------------
class Base{};

//-- A.h ---------------
#include "Base.h"
class A : public Base{} ;

//-- B.h ---------------
class A; // 先行宣言
class B
{
  A* m_pA;
};

//-- B.cpp -------------
#include "Base.h"
void B::Func()
{
   Base* pBase = m_pA; // エラー
}

こんなコードはダメでした。^^;
B.cpp は、class A の型があるのは分るけど、その定義は知らない(継承してることを知らない)ので、ビルドエラーが発生するようです。
解決方法は単純で、B.cpp で A.h を inlucde してあげれば、OKなんです。

……が、私は template関数(<algorithm>) とか併用している状態で上記のような問題に遭遇したため、エラーメッセージが複雑ゆえ、ヘッダのinlucdeし忘れに気づくのに 20分ぐらいかかってしまいました。orz
でも、経験にはなったかなー。