以下のコードはどこか別の所でBokeBoke::Hogeが宣言されているよ、というプロトタイプ宣言です。
class Hogeからは存在の情報だけが露にされているわけです。
C++
1namespace BokeBoke
2{
3 class Hoge;
4}
これによって得られることは、BokeBoke::Hogeを識別できるようになることだけです。
そして、BokeBoke::Hogeが識別できて何がうれしいかというと、参照型ならアクセスできるようになります。
namespace BokeBoke
{
class Hoge;
}
void SomeFunction(BokeBoke::Hoge *p);
この宣言は可能です。
ただし、この宣言からインスタンス化は不可能ですし、できるのは参照の安全な受け渡しのみです。
このような記述は、ヘッダファイル内で別のヘッダファイルを読み込むのを抑制したい場合に役立ちます。
ある複数のモデルを扱うサービスがあったとして、複数のモデル全てをクライアントが使うとは限りません。その場合に、クライアントからサービスにアクセスするのに全てのモデルのヘッダファイルをインポートするのは賢い選択といえるでしょうか。
C++
1// hoge.h
2namespace Model
3{
4 class Hoge
5 {
6 // ...
7 }
8}
9
10// service.h
11#include "hoge.h"
12#include "fuga.h"
13#include "piyo.h"
14
15class Service
16{
17 void AddHoge(Model::Hoge *hoge);
18 Model::Hoge* GetHoge(int hoge_id);
19
20 void AddFuga(Model::Fuga *fuga);
21 Model::Fuga* GetFuga(int fuga_id);
22
23 void AddPiyo(Model::Piyo *piyo);
24 Model::Piyo* GetPiyo(int piyo_id);
25}
こう書かれているよりも以下のようにした方がスコープの穢れは少なくなります。
C++
1// service.h
2namespace Model
3{
4 class hoge;
5 class fuga;
6 class piyo;
7}
8
9class Service
10{
11 void AddHoge(Model::Hoge *hoge);
12 Model::Hoge* GetHoge(int hoge_id);
13
14 void AddFuga(Model::Fuga *fuga);
15 Model::Fuga* GetFuga(int fuga_id);
16
17 void AddPiyo(Model::Piyo *piyo);
18 Model::Piyo* GetPiyo(int piyo_id);
19}
C++
1// client.cpp
2#include "service.h"
3#include "hoge.h"
4
5void Client::SomeFunction(int id)
6{
7 Model::Hoge *hoge = service->GetHoge(id);
8 // do something here
9}
上記はとても簡単なサンプルですが、プロトタイプ宣言の意味はなんとなくわかると思います。
特にヘッダファイルの更新によるオブジェクトファイルのリビルドを抑制することができます。
後者のサンプルであれば"fuga.h/piyo.h"の更新時にclient.cppがリビルドされることはありません。
特に古い巨大なモノリシックアプリケーションでは、このテクニック一つでコンパイル時間がずっと変わってきます。
僕はというと、ヘッダファイル内での名前空間はインデントする派です。
cppファイル内ではしません。cppファイルでは多くても名前空間の宣言は一種類で、それが無名名前空間の宣言だからです。
インライン関数用のファイルでは名前空間を直接記述することがないので当然インデントしません。
(追記:ヘッダファイルは体外的なところで、原則マイルールを適用せず、読みやすく、クリーンで、情報は多くても実コードの少ないファイルにしたいと考えています。一方でCPPファイルは編集時の快適さを求めており、関数の記述開始地点から終了地点までしかファイルを読まない=インデントが無いのが自然と考えているため、ボディとヘッダで違うルールを適用しています。)
// ヘッダファイル
namespace Name
{
class Hoge
{
private:
void Fuga();
void Piyo();
};
}
// インライン関数群
void Name::Hoge::Fuga()
{
// ...
}
// CPPファイル
namespace
{
// ここではインデントしていない
void SomeFunction()
{
}
} // end of namespace
void Name::Hoge::Piyo()
{
// ...
}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/03/15 02:14
2017/03/15 02:52