2016-05-11 8 views
2

いくつかの研究の後で、forward-declareが行うならば、私は#include私のヘッダファイル内のものを避けるべきであることを発見しました。 std::size_tを宣言するにはどうすればよいですか?または、私も#include <cstddef>私のヘッダーファイルにする必要がありますか?フォワードはヘッダ内のstd :: size_tを宣言します

ファイルmy_string.h

#ifndef MY_STRING_H_ 
#define MY_STRING_H_ 

extern std::size_t; 

namespace my 
{ 
     class string 
     { 
     public: 
       std::size_t length() const { return len; } 
       const char *c_str() const; 
     private: 
       std::size_t len; 
     } 
} 

#endif 

ファイルmy_string.cpp:

#include "my_string.h" 

#include <cstddef> 

const char *my::string::c_str() const 
{ 
     for (std::size_t i = 0; i < len; ++i) 
       ;  // do stuff ... 

     return something; 
} 

は明らかにこれらの例は完全ではありません...

私'エラーが発生しました:error: 'size_t' in namespace 'std' does not name a typemy_string.hから)。

編集:お返事ありがとうございます。私はこのヘッダーを含めないように強制しようと時間を無駄にしていると思ったが、私は単純なものを見逃していないことを確かめたかった。

答えて

4

externは、関数と変数用であり、型エイリアス用ではありません。タイプエイリアスはtypedefで定義されます。

これを独自のタイプの1つに対して実行したい場合は、ヘッダからそのtypedefをコピーし、ヘッダのインクルードを避けることができますが、それでもメンテナンス責任を負うコードが重複します。

size_tの場合、その背後にある組み込み型はシステムに依存するため、同じロジックを再現するか、またはリスクの非互換性を再現する必要があります。両方のオプションは、単純にヘッダーを含めるのと比べてかなり悪いです。

+2

'use my_size_t = decltype(sizeof(1));'は移植性があります;)ヘッダーは必要ありません。 – MSalters

+0

@MSaltersこのハックは単に素晴らしいです! :-) :-) :-) – dasblinkenlight

1

size_tはtypedefですが、externで使用することはできません - externは変数または関数とともに使用されます。

それはあなたが前にすべてのことを確認してください場合は十分であろう。そして、常に最初のコンパイラヘッダ(<とonces>)を含むように

#include <cstddef> 

その良い練習がある

#include "my_string.h" 

、およびローカルヘッダー( ""を含む)。

型定義がstd :: size_tとして必要な場合は、ヘッダファイルにも含めます。複数の定義を防ぐために、すべてのヘッダーに適切なインクルードガードが必要です。あなたの.cppファイルにヘッダーだけを含める習慣を守ることは本当に難しいことです。コンパイラは複数のヘッダーインクルードを最適化するのに適していますが、Visual Studioではプリコンパイル済みのヘッダーも提供しています(#pragma once)。

+0

私は複数の場所(Googleのコーディングガイドを含む)から関連するヘッダー、システム/ライブラリヘッダー、その後は他のすべてのローカルヘッダーを読み込んでいます。私はそれが欠落していること(私のクラスのヘッダーを信じている)がこのように気付かれないという事実と関係していると思います。ヘッダが 'std :: size_t'(' len'と 'length()')を参照しているため、 'cstddef'が' my_string.h 'の前に含まれているとは思いません。 – RastaJedi

+1

@RastaJediおかげさまで、興味深いことに、ここに参考のためのリンクがあります:https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes – marcinj

+0

もちろん:参考リンクに感謝したいと思います。 :p。インクルードのためのガイドに従っていないことに注意してください。大きな違いは、Cヘッダの前に* Cヘッダを置くことです。しかし、私は残りの部分は彼らがそれを行うのと同じ方法だと思う。私はそれらのグループ内でアルファベット順か、ファイルに追加する順番を決めなければならないのですか(つまり、Cでは、アルファベット順ではないので、私はまだ100%を何にするか決まっていません) – RastaJedi

4

ライブラリを開発する場合は、ヘッダーファイルにインクルードヘッダーファイルは含めないでください。ただし、常にcppファイルに必要なヘッダーを含める必要があります。 したがって、cppファイルにのみ特定のヘッダーを組み込み、ヘッダーファイルに前方宣言を使用することをお勧めします。 あなたのケースのようにシステムヘッダに依存している場合は、ヘッダファイルにそのシステムヘッダを含める必要があります。

先端は ソースファイルのヘッダ (* .cppファイル、* .C)を含むことにより、我々は、我々が開発したライブラリのリンカの依存関係を解決するために、エンドユーザーを防止していることです。

+0

externは型では動作しませんexternは、与えられた変数または関数に対応するメモリがローカルモジュールに属していないことをコンパイラに通知します。したがって、リンク時に解決する必要があります時間。 –

関連する問題