OK、静的関数とは何かを学びましたが、プライベートメンバー関数よりもなぜ静的関数が有用なのかまだわかりません。これはちょっと新しい質問かもしれませんが、プライベートメンバー関数をすべて静的関数に置き換えるだけではどうですか?
static
ファイルスコープに機能を制限する。
private member
することを考えると、OPがOOの概念について尋ねており、ファイルスコープの静的についての手がかりがないと安全に推測できると思います。
OK、静的関数とは何かを学びましたが、プライベートメンバー関数よりもなぜ静的関数が有用なのかまだわかりません。これはちょっと新しい質問かもしれませんが、プライベートメンバー関数をすべて静的関数に置き換えるだけではどうですか?
static
ファイルスコープに機能を制限する。
private member
することを考えると、OPがOOの概念について尋ねており、ファイルスコープの静的についての手がかりがないと安全に推測できると思います。
回答:
OOPを使用していると仮定すると、クラスメンバーに依存しない静的関数を使用します。それらはまだプライベートにすることができますが、このように、関連オブジェクトのインスタンスに依存しないため、最適化されます。
上記以外にも、1つのパブリック関数を実行するだけでオブジェクトのインスタンスを作成したくない場合に、静的関数が便利だと思います。これは主に、いくつかの反復的な一般的な作業を行うパブリック関数を含むヘルパークラスの場合ですが、呼び出し間で状態を維持する必要はありません。
上記よりも簡単な説明を試みます(かなり良い説明)。
オブジェクトは通常、コード+データです。静的メソッドは、処理する「コード」部分しかない場合に使用されます(維持されるデータ/状態はありません(静的データメンバーを除く))。
インスタンスを必要とせず、パブリックにできるためです。最大公約数を得るための関数が必要だとしましょう(GCD;分数クラスに非常に役立ちます;はい、これは単なる簡単な例です)。オブジェクトのクラスを作成することに意味はありません。オブジェクトのクラスの唯一の目的は、this
で使用する必要のないポインターを使用できるようにすることですgcd
。そのため、静的メソッドを使用します。理想的には、GCDを実際に使用するクラス(たとえば、分数クラス)で使用します。
静的メソッドしかない場合は、OOPが間違っているため、実際にOOPを実行するか、パラダイムにより適した言語を使用する必要があります。
静的メソッドとは:
静的メソッドは、クラスのインスタンスを必要とせず、そのようなインスタンスのデータ(またはthis、self、Meなど)に暗黙的にアクセスすることもできません。[ 1 ]
静的メソッドが有用な場合の例:
適切な場合にのみ使用してください。
データの多くがオブジェクトの外部にあり、静的メソッドを介して処理されている場合、コードはオブジェクト指向ではなく、保守が困難になる可能性があります。
静的とプライベートは実際には直交しています。メソッドは静的、プライベート、またはなし、あるいはその両方です。
静的と非静的(別名「インスタンスメソッド」)は、メソッドがクラス自体(静的)で動作するか、特定のインスタンス(非静的)で動作するかを示します。言語によっては、インスタンスを介して静的メソッドを呼び出すことができますが、静的メソッドを介してインスタンスにアクセスすることはできません(つまり、静的メソッドの内部から非静的メソッドを呼び出すことはできません。this
オブジェクト)。静的メソッドを使用して、概念的にクラスにリンクされているが、特定のインスタンスに「バインド」されていない動作を実装します。静的メソッドを使用する別のシナリオは、クラスの2つのインスタンスで動作する関数があり、どちらのオペランドも特権ステータスに値しない場合です(たとえば、クラスがあると仮定する場合)Vector
、追加を実装したい; 追加メソッドはとして呼び出すことができますa.Add(b)
が、Vector.Add(a, b)
おそらくもっと意味があります。
プライベートとパブリックは、メソッドの可視性に関するものです。プライベートメソッドにはクラスのスコープ内からしかアクセスできませんが、パブリックメソッドにはどこからでもアクセスできます。これの最も重要な用途はカプセル化です:クラスと通信するために残りのコードで絶対に必要なメソッドとプロパティのみを公開することにより、外部コードが問題を引き起こす可能性のあるポイントを制限し、内部の問題を防ぎますクラスがプロジェクトの残りの部分に出血するのを防ぎます。
だから、経験則:
あなたがC ++について話している(あなたは言わなかった)とあなたは正しい用語を持っていると仮定します(すなわち、メンバー関数/メソッドを意味しない):
プライベートメンバー関数でさえ、ヘッダーで宣言する必要があります。つまり、ユーザーが実際に呼び出すことはできなくても、実際にはクラスのAPIおよびABIの一部になります。プライベートメンバー関数を追加、変更、または削除すると、すべての依存クラスの再コンパイルが強制され(ヘッダーが変更され、makeの方がわかりにくくなります)、ライブラリで行う場合は、アプリケーションの互換性を考慮する必要がありますそれ。
一方、ファイルスコープの静的関数はパブリックシンボルを取得しないため、必要に応じて追加、変更、または削除することができ、1つのコンパイルユニット以外は影響を受けません。
通常、プログラムのエントリポイントとして機能する静的メインが必要です。それはちょっと重要かもしれません。
静的関数(および異なる言語ではその用語には異なる意味があります)は、呼び出し間で保持される状態を必要としません。概念的にクラスの動作と密接に結びついている場合は、クラス関数(オブジェクトではなくクラスのように)にするか、そうでない場合はグローバル(またはモジュールレベルなど)の関数にします。オブジェクトの状態を必要としない場合、オブジェクトに属しません。
常にステートを渡しており、それが実際にはステートレス関数ではない場合、ステートレス構文でステートフル関数を作成しているだけです。その場合、おそらく呼び出し元のオブジェクトに属しているか、状態と動作をより良く調整するためのリファクタリングが示されている可能性があります。
誰もまだ良い答えを出すことができなかったのは面白いです。これがどちらなのかわかりません。あなたはおそらく、それらを可能な限り少なく使用すべきであるというヒントとしてそれをとるべきです。結局のところ、OOPではなく手続き型です。
以下に例を示します。
クラスメソッドと呼ばれるObj-Cでは、オブジェクトが返される前に参照カウントプールに配置される割り当てラッパーとして一般的に使用されます。
Obj-Cの別の例は、新しいクラスをクラスコレクションに登録することです。それぞれが1種類のファイルを処理するクラスのセットがあるとします。新しいファイルタイプの新しいクラスを作成する場合、ファイルのタイプを決定するクラスの静的メソッドを使用して、コレクション(グローバル変数)に登録できます。
C ++で考えられるもう1つの用途は、エラーをソフトにキャッチすることです。例外をスローしない限り、コンストラクター関数は失敗しません。エラーインスタンス変数を設定することもできますが、それが常に適切とは限りません。代わりに、静的ラッパーで失敗する可能性のある部分を実行してから、新しいオブジェクトを割り当てて返すか、失敗するとNULLを返すことができます。
何かの洞を計算したいとしましょう。
静的なし:
Math math = new Math()
double y = math.sin(x)
静的な場合:
double y = Math.sin(x)
sin
非静的にすることは意味がありません。ステートレスであり、入力を処理するだけです。
静的関数は特定のオブジェクトに関連付けられていません。これらは、オブジェクトの内部状態に依存しない「一般的な」機能です。
x.sin()
。あなたの答えは、罪は「数学」の関数であるべきだと仮定していますが、それは明らかに二重に作用しています。
ここで遅くなりましたが、正確な定義を作成したいと思います。静的関数は、含まれるクラスのインスタンスプロパティ/メソッドを参照しない、または参照できない関数です。
C#などの一部の言語では、静的クラスに静的フィールドまたは静的プロパティが存在する場合があるため、状態に使用されていないと言うのは正しくありません。静的関数は静的(グローバル)状態を利用する場合があります。
基本的に、要約すると、静的関数は、静的なものと同様に、静的でないインスタンスに依存せずに常に使用できることが理にかなっている場合に役立ちます。
数学関数のようなヘルパー関数は、よくある例ですが、他にもあります。
作成するクラスでデータが不変であることが必要な場合、インスタンスを変更して静的インスタンスを取得し、新しいインスタンスを渡す静的関数を作成することは理にかなっています。たとえば、文字列クラスには、文字列(または2つ以上)を取り込んで新しい文字列を返す静的関数があります。
もう1つの理由は、何らかのグローバルな状態またはデータを保持するクラスがあることです。その静的クラスの静的プロパティまたはフィールドで動作する静的関数が存在する場合があります。
静的f()の別の使用法を指摘したいと思います。
http://www.parashift.com/c++-faq/named-ctor-idiom.html
要するに、static
関数を使用すると、「名前付きコンストラクター」を作成できます。つまり、適切な自己文書化名で静的関数に名前を付けます。この静的関数は、コンストラクターの1つを呼び出します(コンストラクターは、それらの多くは、それらを区別するのが難しくなります)。