2

別の cpp ファイルにインクルードしたいヘッダー ファイルがあります。このようにヘッダファイルを書いたらどう違うのか知りたいのですが、

#include <iostream>
#include <string>
using namespace std;

string ret()
{
return "called";
}

===================================

#include <iostream>
#include <string>
using namespace std;

static string ret()
{
return "called";
}

ret()とにかく関数にアクセスできます!! それで、スタティックの用途は何ですか?

4

4 に答える 4

5

それはあなたが示しているかなり邪悪なヘッダー ファイルです。

  1. using namespace std;ヘッダー ファイルには入れないでください。これにより、ヘッダーを含むすべての人stdがグローバル名前空間にすべてを持つようになります。

  2. 何らかの形式のインクルード ガードを使用します。

  3. static関数が含まれている場所の外では関数を非表示にします.cpp。これは、ヘッダーを含むすべて.cppのものが独自の関数のコピーを持つことを意味します。static(非メンバー) 関数は、特にこの動作が必要な場合にのみ使用してください。

  4. を使用しない場合はstatic、定義をヘッダーからソース ファイルに移動するか (一度定義したい場合)、関数を宣言する必要があります (可能であれば、inlineそのコードはすべての呼び出しサイトでインライン化されます)。これらのいずれも行わないと、ヘッダーを複数のソース ファイルに含めると、複数の定義エラーが発生します。

于 2013-01-08T09:06:46.107 に答える
4

最初のヘッダー ファイルは、retそれを含むすべての翻訳単位の外部リンケージで呼び出される関数を定義します。このような TU が同じプログラムで複数リンクされている場合、これは正しくありません。

2 番目のヘッダー ファイルは、retそれを含むすべての翻訳単位の内部リンケージで呼び出される関数を定義します。これは、いくつがリンクされていても、各 TU が関数の独自のプライベート コピー (異なるアドレスを持つ) を持つことを意味します。

ヘッダー ファイルを使用してコードを共有するには、次の 3 つの正しい方法があります。

  • 内部リンケージを持つ関数 (2 番目のヘッダー、または名前のない名前空間に配置することによる C++11 のように)。
  • static外部リンケージを持つインライン関数 ( に置き換えinlineます)。の意味はinline、プログラム内に関数のコピーが 1 つしかないにもかかわらず、その関数を使用するすべての TU にその定義が含まれているということです。
  • ヘッダーで関数を宣言し、その中で正確に 1 つの .cpp ファイル (たとえば ret.cpp) を定義します。

C++03 には 4 番目の方法がありました。

  • 名前のない名前空間で外部リンケージを持つ関数

これは C++11 でも利用できると思いますが、C++11 では名前のない名前空間の関数はデフォルトで内部リンケージを持っています。名前のない名前空間の関数に外部リンケージを持たせるための C++11 の使用については知りません。したがって、関数に関する限り、名前のない名前空間は、関数に内部リンケージを与える良い方法です。

どちらを使用するかは、ニーズによって異なります。3 番目のオプションは、呼び出しコードを再コンパイルせずに関数の定義を変更できることを意味しますが、関数が dll にない限り、実行可能ファイルを再リンクする必要があります。

最初の 2 つ (staticまたはinline) は、次の場合に動作が異なります。

  • 関数にはstaticローカル変数が含まれています。
  • 関数ポインターをret異なる TU で取得したものと比較し、
  • 実行可能ファイルのサイズまたはシンボル テーブルを調べます。
  • 関数の定義は TU ごとに異なります (おそらく #defines が異なるため)。これは、関数に外部リンケージがある場合は禁止されていますが、内部リンケージがある場合は禁止されていません。

それ以外はほとんど同じです。

標準によれば、inlineは、高速実行のためにコンパイラがその関数への呼び出しを最適化する必要があるというヒントでもあります (実際には、呼び出しサイトでコードをインライン化することを意味します)。ほとんどのコンパイラは、ほとんどの場合、このヒントを無視します。インライン化の良い候補であると評価した場合、staticしかし関数ではない関数を喜んでインライン化し、インライン化の悪い候補であると評価した場合、喜んで関数のインライン化を回避します。inlineinline

于 2013-01-08T09:06:55.370 に答える
2

ヘッダー ガードを使用します。

ヘッダー ファイルで「using namespace」を使用しないでください。(実際には、ヘッダー ファイルで「using」を使用しないでください。完全修飾された識別子を使用してください。)

また、関数を定義するためではなく、関数を宣言するためにヘッダーを使用します。のコードは、結果の実行可能ファイルに一だけ存在する必要があります。これを行うには、 の定義 (コード) を.cpp ファイルに入れます。複数のファイルではなく、 1 つの.cpp ファイル (定義を含めることにより)。ret()ret()

ヘッダー ファイルには関数の宣言がリストされてret()いるため、他のコードは、関数が存在し、どのパラメーターを受け取り、何を返すかを「認識」します。

于 2013-01-08T09:09:33.517 に答える
1

ヘッダー ファイルのようにc++ メソッドを定義するとstatic、各変換単位 (そのヘッダー ファイルを含む各 .cpp ファイル) には、それらの静的メソッドの異なるバージョンが含まれます。同じアドレス空間はありません。したがって、プログラムのサイズが不必要に大きくなります。

また、わかりやすくするために:

メソッドを .cpp ファイルのみとして定義するstaticということは、メソッドに静的リンケージがあり、同じ .cpp ファイル内の他のメソッドからのみアクセスできることを意味します。

于 2013-01-08T09:15:43.850 に答える