1

グローバル変数と魔法数は、プログラミングの際、特にプロジェクト内のコードの量が増えるにつれて避けるべきものであることを私は知っており、理解しています。しかし、私は両方を回避するための良い方法を考えることができません。

画面幅を表す事前に決定された変数があり、その値が複数のファイルで必要であるとします。私はそれをできた...

doSomethingWithValue(1920);

しかし、それは魔法の数です。しかし、それを避けるために、私はします...

const int SCREEN_WIDTH = 1920;

//In a later file...
extern const int SCREEN_WIDTH;
doSomethingWithValue(SCREEN_WIDTH);

そして今、私はグローバル変数を使用しています。ここでの解決策は何ですか?

4

10 に答える 10

11

2番目の例でSCREEN_WIDTHは、は実際には変数1ではなく、名前付き定数です。名前付き定数を使用しても問題はありません。

Cでは、constオブジェクトは定数ではないため、整数定数の場合は列挙型を使用することをお勧めします。C ++では、constオブジェクトは定数であるため、元の質問のようにconstオブジェクトを使用することをお勧めします。

1.技術的には、はい、それは「変数」ですが、その名前は変更されないため、実際には「正しい」ものではありません。

于 2010-09-09T22:55:24.257 に答える
5

ヘッダーファイルの名前空間内で定数を定義することをお勧めします。その場合、スコープはグローバルではなく、複数の場所で(externキーワードを使用しても)再定義する必要はありません。

于 2010-09-09T23:00:07.087 に答える
2

そもそもなぜ画面幅をハードコーディングする必要があるのですか?それはどこから来たのですか?ほとんどの実際のアプリケーションでは、現在実行している解像度、またはシステムが表示できる解像度を通知するシステムAPIから取得されます。

次に、その値を取得して、必要な場所に渡します。

要するに、この行で:doSomethingWithValue(SCREEN_WIDTH); あなたはすでにそれをやっています。この特定の例ではグローバルである可能性がありますが、関数がグローバルとしてアクセスしてSCREEN_WIDTHいないため、グローバルである必要はありません。実行時に値を関数に渡すので、関数が認識するのはグローバル変数ではなく、単なる関数の引数です。

もう1つの重要な点は、不変のグローバルデータには通常何も問題がないということです。

通常、グローバル定数は問題ありません。この問題は、変更可能なグローバル状態がある場合に発生します。つまり、アプリケーション全体でアクセスできるオブジェクトであり、いつ見るかによって値が異なる可能性があります。それは推論を難しくし、多くの問題を引き起こします。

しかし、グローバル定数は安全です。円周率を例にとってみましょう。これは数学定数であり、すべての関数にpiが3.1415であると認識させても問題ありません。それが3.1415であり、変更されないためです。

画面幅がハードコードされた定数である場合(例のように)、それも大混乱を引き起こすことなくグローバルにすることができます。(明らかな理由からですが、そもそも定数であってはならないでしょう9

于 2010-09-09T22:57:59.280 に答える
1

これは変数ではなく定数であり、コンパイル時に解決されます。

とにかく、そのような「浮動」定数が気に入らない場合は、名前空間などに入れて、そのタイプのすべての定数をまとめることができます。場合によっては、関連する定数をグループ化する列挙型を検討することもできます。

さらに良いことに、これが状況に当てはまる場合は、固定された所定の画面幅の使用を避け、実行時に正しいAPIを使用してそれを取得してください。

于 2010-09-09T22:58:13.150 に答える
1

グローバルが必須の場合は、通常、グローバルを関数でラップし、関数を使用して値を取得することをお勧めします。

役立つかもしれない別の投稿

于 2010-09-09T22:58:38.030 に答える
1

2番目のケースのグローバルはかなり無害ですが、画面の幅が変わらないことが確実なもののためにこれを設計していない限り、画面の幅を動的に取得するために何かを使用します(たとえば、 GetSystemMetricsWindowsの場合) 、またはXDisplayWidthX上)。

于 2010-09-09T23:04:03.670 に答える
1

グローバル変数の主な問題は、それらが非定数である場合です。変化しないグローバルは、使用されている場所ならどこでもその価値を常に知っているので、それほど心配する必要はありません。

この場合、1つの正しいアプローチは、定数名前空間を作成し、そこに定数値を配置して、プログラム内の任意の場所で参照できるようにすることです。これは2番目の例によく似ています。

于 2010-09-09T22:56:57.193 に答える
1

それらはどこかで定義する必要があります。定義を.hファイルまたはビルドファイルに入れてみませんか?

于 2010-09-09T22:57:29.433 に答える
1

これを回避する1つの方法は、プログラムをオブジェクトとして設定し、オブジェクトにプロパティ(my_prog.screen_width)を設定することです。プログラムを実行するには、main()でオブジェクトをインスタンス化し、オブジェクトに対して->goメソッドを呼び出します。

Javaはこれを行います。多くの。半ばまともなアイデア。

プログラムの拡張のためのボーナス機能:

  • プログラムをいつかカスタマイズ可能にすると、すべてを再コンパイルする代わりに、コンストラクターでプロパティを設定することができます。
  • プログラムの2つのインスタンスを同じプロセスで隣り合わせに実行する場合は、設定を変えることができます。

ただし、1回限りの簡単なプログラムとしては大したことではありません。

于 2010-09-09T23:16:43.083 に答える
0

グローバル定数でさえ、将来変更する必要がある場合に問題を引き起こす可能性があることを認識することが重要です。場合によっては、単にそれらを変更させないことを決定することもありますが、そうでない場合もあります。たとえば、プログラムに画面に合わせたサイズのグラフィック画像が含まれている場合があります。異なるサイズの画面で実行するように調整する必要がある場合はどうなりますか?名前付き定数を変更するだけでは、プログラムに埋め込まれているグラフィックイメージが必ずしも修正されるわけではありません。実行時に使用する画面のサイズを決定できる必要がある場合はどうなりますか?

考えられるすべての不測の事態に対処することは不可能であり、単に起こらないことから保護するために一生懸命努力するべきではありません。それにもかかわらず、人は自分自身を隅に追いやることを避けるために、物事が何を変えることができるかについて注意する必要があります。

クラスを設計するときに、不変の値を返す仮想読み取り専用プロパティを使用すると、クラスの将来の拡張で異なる値を返すことができます。定数ではなくプロパティを使用すると、パフォーマンスに影響が出る場合がありますが、場合によっては、柔軟性に見合うだけの価値があります。仮想定数を定義する方法があればいいかもしれませんが、.netがそれを許可することが理論的に不可能である理由はわかりません(仮想メソッドポインタを含むテーブルに定数値を含めます)が、これまでのところ私はそうではないことを知っています。

于 2010-09-09T23:44:57.007 に答える