web-dev-qa-db-ja.com

静的メンバー関数がクラス定義内でのみ静的に宣言でき、それ自体の定義内でも宣言できないのはなぜですか?

画面上でボックスを作成/更新するためのクラスを実装しているときに、現在表示されているボックスが重ならないようにする静的メンバー関数を追加したいと思いました(静的ポインター配列から現​​在表示されているすべてのボックスに情報を取得します)

私の最初のコードは次の構造でした:

class Box
{
public:
    // ...
    static void arrangeOverlappingBoxes();
};

static void Box::arrangeOverlappingBoxes()
{
    // ...
}

これによりエラーC2724が生成されたことに非常に驚きました。ファイルスコープで定義されたメンバー関数で「static」を使用しないでください。

いくつかの試行錯誤の結果、関数定義でキーワードstaticが失われるはずであることがわかりました。つまり、次のようになります。

void Box::arrangeOverlappingBoxes()
{
    // ...
}

しかし、私にはこれの背後にある理論的根拠が何であるかについての手がかりがありません。クラス定義とそれ自体の定義での宣言に異なる関数ヘッダーがあることは、非常に非対称で混乱しているように見えます。これには何か理由がありますか?

16
mr_T

(ヘッダーファイル内の)クラス定義は、必要なプロパティを関数に提供します。

  • 静的
  • インライン化
  • バーチャル

それ以降のすべてのオブジェクトが.hを使用してクラス定義を参照することを考えると、これらのプロパティをそこで定義することは理にかなっています。

さらに、クラスの各関数は、派生クラスでそのプロパティを維持します(たとえば、基本クラスでのみデストラクタを仮想として宣言する必要があります。後続の継承はすべて、デストラクタを仮想として受け取ります)。

実装本体でこれらのプロパティを再宣言することは意味がありません。

.hファイルと.cppファイルの両方で関数のプロパティを宣言する必要があると、実際には多くの問題が発生します。このシナリオを想像してみてください。関数を.hファイルでは仮想として宣言し、.cppファイルでは静的として宣言します。コンパイラはその関数を何にしますか?仮想または静的? (または、コンパイルエラーの可能性が高くなりますが、コンパイラエラーは、.cppファイルでヘッダーの宣言と一致するように促します。「静的」または「仮想」に従って関数をオーバーロードすることはできません)。

10
MichaelCMS