0

これが重複している場合は申し訳ありませんが、私が見つけたもの...まあ、同じ解決策を試したと思いましたが、役に立ちませんでした。とにかく、私は最近、一般的に使用されるランダム関数の実装を単一のヘッダー ファイルに移動しようとしました。関数がどのように機能するかは知っていますが、すぐに変更することはないので、ファイルが少ないほど良いと考えました (そして、関数はかなり短いです)。

それで、私はそれを試しました。.cpp ファイルの内容を新しいファイルに貼り付け、ガードを追加しました。次に、それを含めるだけで、出来上がりです。残念ながら、それを 2 回含めたところ、同じ関数のコピーをすべてのファイルに配布していたため、エラーが発生しました。(とにかく 1 つのコピーになってしまうため、なぜそれがヘッダー ガードにあるのか、まだ少し混乱していますが、そうなっていると思います)。とにかく、私はググって(そしてSO'ed)、それらをインラインとして宣言した場合(この状況では理にかなっています)、プリプロセッサ(またはリンカでもありますか?)がそれを正しく行うことを発見しました。考えてみると...小さな質問として、DEFINESはファイルに対してローカルですか、それともスコープ内でグローバルですか? (つまり、定義するヘッダー ガードを使用して 2 つのファイルにヘッダーをインクルードする場合、定義が異なるファイルで発生したため、両方のファイルにそれをインクルードしますか? それとも一度だけ?それが2回含まれていた場合、同じ関数/クラス/構造の複数の宣言を取得します(定義はしません)。これはエラーをスローすると思いましたが、別のファイルには含まれていないと思いますか? ただし、それ以外の場合は、含まれていない可能性があり、それが何であるかを認識できません。もう一度質問しますが、DEFINES はファイルに対してローカルですか? )

これは、関数が重複するファイルにあるものです(1つの関数しか含まれていないと考えられていました)

#ifndef RANDOM_H
#define RANDOM_H

//needed for getting system time and for random generation functions rand and srand
#include <time.h>
#include <stdlib.h>

//this function returns a random number between an inclusive range
inline int randomRange(const int & min, const int & max)
{
    if (max >= min)
        return ((rand() % (max+1-min))+min);
    else
        return ((rand() %  (min+1-max))+max);
}

#endif

次に、このファイル (「random.h」) の 2 つのファイルに #include を含めるだけです。

私は何が欠けていますか?

編集:エラーメッセージは:

`randomRange(int const&, int const&)' の多重定義 |

少し休憩している間に、IDE を閉じていました。再開すると、すべてが修正されました。明らかに、インライン DID を追加すると修正されますが、実行時の cpp ファイルとは異なり、ヘッダー ファイル (プロジェクトに追加されていない場合) は、手動で保存しない限り更新されません。保存したら動作しました。すみません、皆さん。

今日の教訓: このようなエラーを修正するときは、ファイルが更新されていることを確認してください...

4

1 に答える 1

0

マクロ定義は翻訳単位に対してローカルです。ソース ファイルをコンパイルするとき、プリプロセッサはさまざまなプリプロセッサ ディレクティブ ( 、 など) を展開#define#include、結果を実際のコンパイラに渡します。これは、1 回だけでなく、ファイルごとに 1 回行われます。ガードを含める理由は、同じヘッダーが同じ翻訳単位に 2 回含まれる可能性が非常に高いためです。たとえば、Pointクラスで使用されるRectangleとのタイプがあり、 とTriangleの両方のヘッダーを含めるRectangleと、 2 回Triangleのヘッダーを含む翻訳単位になります。Point

ヘッダーで関数を定義するときは、グローバルに可視な定義にすべきではないことをコンパイラーに示す必要があります。通常の方法はinlineこれを使用することです。これは、意味がある場合は関数を呼び出さないようにする必要があることをコンパイラーに示します。を使用する代わりにinline関数を作成することstaticもできますが、その場合、実際には最終的な実行可能ファイルに関数の複数のコピーが作成されることになります: コンパイラがinlineすべての翻訳単位で関数のバージョンを使用する場合でも、リンク時に 1 つが選択され、どこからでも使用されます (他のすべてのコピーが破棄されることを願っています)。staticたとえば、関数にローカル変数がある場合、違いが見られます。

inline int f() {
    static int rc(0);
    return ++rc;
}
static int g() {
    static int rc(0);
    return ++rc;
}

f()これらの関数をg()異なる翻訳単位から呼び出すと、後者にはファイルごとのカウンターがあり、前者にはグローバルカウンターがあります。

于 2012-10-06T17:45:19.473 に答える