585

C++ でプライベートな静的データ メンバーを初期化する最良の方法は何ですか? ヘッダーファイルでこれを試しましたが、奇妙なリンカエラーが発生します:

class foo
{
    private:
        static int i;
};

int foo::i = 0;

これは、クラスの外部からプライベート メンバーを初期化できないためだと思います。では、これを行う最善の方法は何ですか?

4

18 に答える 18

618

クラス宣言は、ヘッダー ファイル (または、共有されていない場合はソース ファイル) にある必要があります。
ファイル: foo.h

class foo
{
    private:
        static int i;
};

ただし、初期化はソース ファイルで行う必要があります。
ファイル: foo.cpp

int foo::i = 0;

初期化がヘッダー ファイルにある場合は、ヘッダー ファイルを含む各ファイルに静的メンバーの定義が含まれます。したがって、変数を初期化するコードが複数のソース ファイルで定義されるため、リンク フェーズ中にリンカー エラーが発生します。の初期化は、static int i関数の外で行う必要があります。

注:int Matt Curtis: 静的メンバー変数が const int 型 (たとえば、bool、 )の場合、C++ では上記を簡略化できると指摘していますchar。その後、ヘッダー ファイルのクラス宣言内でメンバー変数を直接宣言して初期化できます。

class foo
{
    private:
        static int const i = 42;
};
于 2008-10-09T03:36:11.197 に答える
104

変数の場合:

foo.h:

class foo
{
private:
    static int i;
};

foo.cpp:

int foo::i = 0;

foo::iこれは、プログラム内にのインスタンスが 1 つしか存在できないためです。extern int iこれは、ヘッダー ファイルとint iソース ファイルに相当するものです。

定数の場合、値をクラス宣言に直接入れることができます。

class foo
{
private:
    static int i;
    const static int a = 42;
};
于 2008-10-09T03:41:40.607 に答える
33

この質問の将来の閲覧者のために、monkey0506 が示唆していることを避ける必要があることを指摘したいと思います。

ヘッダー ファイルは宣言用です。

.cppヘッダー ファイルは、直接または間接的にファイルごとに 1 回コンパイルされ#includes、関数の外部のコードはプログラムの初期化時に実行されますmain()

:foo::i = VALUE;をヘッダーに入れると、すべてのファイルに (それが何であれ)foo:i値が割り当てられます。これらの割り当ては、実行前に (リンカによって決定される) 不確定な順序で行われます。VALUE.cppmain()

ファイル#define VALUEの 1 つで別の番号になったらどうなるでしょうか。.cppこれは正常にコンパイルされ、プログラムを実行するまでどちらが勝つかはわかりません。

ファイルを入れないのと同じ理由で、実行したコードをヘッダーに入れないで#includeください.cpp

インクルードガード(常に使用する必要があることに同意します)は、別の何かからあなたを保護します:#include単一の.cppファイルのコンパイル中に同じヘッダーが間接的に複数回dされます

于 2012-12-27T15:37:38.523 に答える
23

Microsoft コンパイラ [1] を使用すると、-like ではない静的変数intもヘッダー ファイルで定義できますが、Microsoft 固有の__declspec(selectany).

class A
{
    static B b;
}

__declspec(selectany) A::b;

これが良いと言っているのではなく、できると言っているだけです。

[1] 最近では、MSC をサポートするコンパイラよりも多くのコンパイラ__declspec(selectany)(少なくとも gcc と clang) がサポートされています。多分もっと。

于 2008-10-09T05:45:26.177 に答える
18
int foo::i = 0; 

Is the correct syntax for initializing the variable, but it must go in the source file (.cpp) rather than in the header.

Because it is a static variable the compiler needs to create only one copy of it. You have to have a line "int foo:i" some where in your code to tell the compiler where to put it otherwise you get a link error. If that is in a header you will get a copy in every file that includes the header, so get multiply defined symbol errors from the linker.

于 2008-10-09T03:42:18.873 に答える
9

これをコメントとして追加するのに十分な担当者がここにはいませんが、IMO では、数時間前に Paranaix が指摘したように、#include ガードを使用してヘッダーを記述することをお勧めします。これにより、複数定義エラーが防止されます。別の CPP ファイルを既に使用していない限り、静的な非整数メンバーを初期化するためだけに使用する必要はありません。

#ifndef FOO_H
#define FOO_H
#include "bar.h"

class foo
{
private:
    static bar i;
};

bar foo::i = VALUE;
#endif

これには別の CPP ファイルを使用する必要はないと思います。もちろんできますが、そうしなければならない技術的な理由はありません。

于 2012-01-07T19:42:54.520 に答える
4

私はカールのアイデアに従います。気に入って今も使っています。表記を少し変更し、いくつかの機能を追加しました

#include <stdio.h>

class Foo
{
   public:

     int   GetMyStaticValue () const {  return MyStatic();  }
     int & GetMyStaticVar ()         {  return MyStatic();  }
     static bool isMyStatic (int & num) {  return & num == & MyStatic(); }

   private:

      static int & MyStatic ()
      {
         static int mStatic = 7;
         return mStatic;
      }
};

int main (int, char **)
{
   Foo obj;

   printf ("mystatic value %d\n", obj.GetMyStaticValue());
   obj.GetMyStaticVar () = 3;
   printf ("mystatic value %d\n", obj.GetMyStaticValue());

   int valMyS = obj.GetMyStaticVar ();
   int & iPtr1 = obj.GetMyStaticVar ();
   int & iPtr2 = valMyS;

   printf ("is my static %d %d\n", Foo::isMyStatic(iPtr1), Foo::isMyStatic(iPtr2));
}

これは出力します

mystatic value 7
mystatic value 3
is my static 1 0
于 2013-12-31T14:45:25.823 に答える
3

また、privateStatic.cpp ファイルで作業:

#include <iostream>

using namespace std;

class A
{
private:
  static int v;
};

int A::v = 10; // possible initializing

int main()
{
A a;
//cout << A::v << endl; // no access because of private scope
return 0;
}

// g++ privateStatic.cpp -o privateStatic && ./privateStatic
于 2014-01-26T11:21:05.630 に答える
0

これはあなたの目的に役立ちますか?

//header file

struct MyStruct {
public:
    const std::unordered_map<std::string, uint32_t> str_to_int{
        { "a", 1 },
        { "b", 2 },
        ...
        { "z", 26 }
    };
    const std::unordered_map<int , std::string> int_to_str{
        { 1, "a" },
        { 2, "b" },
        ...
        { 26, "z" }
    };
    std::string some_string = "justanotherstring";  
    uint32_t some_int = 42;

    static MyStruct & Singleton() {
        static MyStruct instance;
        return instance;
    }
private:
    MyStruct() {};
};

//Usage in cpp file
int main(){
    std::cout<<MyStruct::Singleton().some_string<<std::endl;
    std::cout<<MyStruct::Singleton().some_int<<std::endl;
    return 0;
}
于 2016-09-02T11:50:33.643 に答える