34

私は Java 開発者であり、C++ の初心者です。ある種のユーティリティ クラスを実装する必要があり、メソッドを静的に実装することを考えていました。ただし、名前空間関数と静的メソッドに関するこのスタックオーバーフローの質問に出くわしました。どうやら名前空間関数が推奨されるアプローチです。そのため、名前空間機能の実装方法に関する記事や例があれば教えてください。たとえば、ヘッダー ファイルで名前空間関数をどのように宣言すればよいですか? ヘッダーにはクラス ヘッダー ファイルのような関数定義のみを含め、実装は cpp ファイルに含める必要がありますか、それともヘッダー ファイルに関数をすぐに実装する必要がありますか?

基本的に、いくつかのコマンドを含むテキスト ファイルを解析するアプリケーションを実装しようとしています。そのため、テキスト処理を処理する静的ヘルパー メソッドを実装することを考えています。例 readCommand(string line)。私が間違った方向にいる場合はお知らせください。ありがとう

4

3 に答える 3

31

ヘッダーファイルで名前空間関数を宣言するにはどうすればよいですか?

namespace MON {
// extern:
t_ret func(const t_param& pValue);
// 'inline':
inline t_ret inline_func(const t_param& pValue) { ... }
} // << MON

ヘッダーにはクラス ヘッダー ファイルのような関数定義のみを含め、実装は cpp ファイルに含める必要がありますか、それともヘッダー ファイルに関数をすぐに実装する必要がありますか?

それは、(潜在的に) インライン化するかエクスポートするかによって異なります。これは多くの場合、依存関係を最小限に抑えることに帰着します。

エクスポートまたはインライン展開を拡張するには:

C++ での依存関係を最小限に抑えるために、extern 関数を使用することがよくあります。これは、クラス メソッドで定義を宣言から分離することと同じです。

ファイル.hpp

namespace MON {
// extern:
t_ret func(const t_param& pValue);
} // << MON

ファイル.cpp

#include "hefty_stuff.hpp"

MON::t_ret MON::func(const t_param& pValue) { ... }

ただし、多くの場合、パフォーマンスのために、またはサイズが重要であり、ヘッダーが多くの場所に含まれていないことがわかっている場合など、場合によっては定義を表示することが重要な場合があります。したがって、inlineバリアントもオプションです。

インライン関数は引き続きエクスポートされる可能性があり、要求に応じてインライン化される可能性があります。ただし、インライン関数のコピーはマージされる可能性があります (具体的には、実装は、すべての定義が等しく、関数のコピーが不要であると自由に想定できます)。

エクスポートされた定義を使用すると、インクルードの依存関係を選択的に制限 (または隔離) できます。つまり#include "hefty_stuff.hpp"、 の関数を使用するためにヘッダーにある必要はありませんfile.hpp


基本的に、いくつかのコマンドを含むテキスト ファイルを解析するアプリケーションを実装しようとしています。そのため、テキスト処理を処理する静的ヘルパー メソッドを実装することを考えています。

まあ、staticここは避けるべきです。c++ は、1 つの定義規則を使用します。static不要なコピーが大量に発生するだけです。さらに、匿名名前空間は、c のstatic関数に対する c++ のアプローチです。

namespace {
t_ret func(const t_param& pValue) { ... }
} // << anon

注: 匿名の名前空間も、不要なコピーになる可能性があります。静的関数の代わりにそれらを使用する理由は、1 つの定義規則から逸脱したい、または逸脱する必要があり、「解決」される可能性のあるスコープでシンボルを宣言したくない場合です。


最後のポイントは、template<>宣言に関するものです。テンプレートを使用する場合、コンパイラが extern テンプレートをサポートしていない限り、使用されている場所で定義を表示する必要があります。テンプレートの場合、複数の方法で定義の可視性を実現できます。通常、人々は単に定義をその場で宣言するか、ヘッダーの最後または必要に応じて含まれる定義のヘッダーを追加します。inlineテンプレートでは、複数の定義エラーを回避するために関数を宣言する必要はありません。

于 2012-05-08T05:23:45.733 に答える
21

ヘッダーで関数を宣言できます。

namespace A {
    void foo();
}

.cpp に実装します。

namespace A {
  void foo() { std::cout << "foo!"; }
}

実装をヘッダーに配置して、 1 つの定義ルールinlineを破らないように宣言することもできます。

namespace A {
    inline void foo() { std::cout << "foo()!"; }
}

実装をヘッダーに配置するということは、実装に使用されるヘッダーだけでなく、実装にもクライアント コードがコンパイル依存関係を持つことを意味することに注意してください。上記の例では、クライアント コードはヘッダーに依存するようになりました。プリントアウトに感嘆符を追加するなどの些細なことを行う場合は、すべてのクライアント コードを再リンクするのではなく、再コンパイルする必要があります。

テンプレート関数の実装をヘッダーまたはヘッダーに含まれるファイルに配置することは非常に重要です。これらは .cpp に入れることはできません。

namespace B {
  template <class T>
  inline void foo(const T& t) { std::cout << t.name() << "\n"; }
}
于 2012-05-08T05:24:53.830 に答える
2

ヘッダーファイルで名前空間関数を宣言するにはどうすればよいですか?

namespace YourNamespace
{
    void fun1();
    void fun2();
}

ヘッダーにはクラス ヘッダー ファイルのような関数定義のみを含め、実装は cpp ファイルに含める必要がありますか、それともヘッダー ファイルに関数をすぐに実装する必要がありますか?

名前空間の関数が静的である場合、関数をヘッダー ファイルに実装するか、cpp ファイルに実装する必要があります。

于 2012-05-08T05:17:00.803 に答える