0

A の cstr で B::SYMBOL がまだ初期化されていないため、以下のコードではセグメンテーション違反が発生することを理解しています。しかし、なぜ?

実際には、A は、B のようなクラスの SYMBOL をそれぞれの ID にマップするマップとして機能するオブジェクトです。C は、クラス関数としてマッピングを提供できるように、この map(A) を静的に保持します。

A の主な機能は、起動時に自身を初期化する C のマップとして機能することです。コードで B::ID と B::SYMBOL を引き続き使用できる場合 (#define pls なし)、セグメンテーション違反なしでそれを行うにはどうすればよいですか?

(ps。インクルードガードを実装したと仮定します)

//A.h
    #include "B.h"
    class A
    {
    public:
      A()
      {
        std::cout<<B::ID<<std::endl;
        std::cout<<B::SYMBOL<<std::endl;
      }
    };

//B.h    
    class B
    {
    public:
      static const int ID;
      static const std::string SYMBOL;
    }

//B.cpp    
    #include "B.h"
    const int B::ID = 1;
    const std::string B::SYMBOL = "B";

//C.h    
    #include "A.h"
    class C
    {
    public:
      static A s_A;
    };

//C.cpp    
    #include "C.h"
    A C::s_A;

//main.cpp    
    #include "C.h"
    int main(int c, char** p)
    {
    }
4

2 に答える 2

1

s_A の遅延初期化を使用します。これはうまくいくかもしれません:

class C
{
public:
  static A& getA() { static A s_A; return s_A; }
};

または:

class C
{
public:
  static A& getA() 
  { 
    if( ps_A == NULL) ps_A = new ps_A; 
    return *ps_A; 
  }
private:
  static A* ps_A;
};

A* C::ps_A = NULL;

どちらのソリューションもスレッドセーフではありません。

于 2010-04-14T20:00:06.420 に答える
1

あなたが話しているセグメンテーション違反は何ですか?Bのメンバー(およびBそれ自体) がの前に宣言されていないため、コードは単にコンパイルされませんA::A()。コンパイラは単に何が何でBあるかを知りません。

と の定義を交換するAB、コードがコンパイルされて正常に動作するはずです。すべてが同じ翻訳単位にある限り、の静的メンバーの定義が の定義Bより前にあると仮定すると、初期化の順序に問題はないはずです。同じ翻訳単位で定義されたオブジェクトは、定義された順序で初期化されます。つまり、開始時までに、の静的メンバーは既に初期化されています。提示されているように、この場合、セグメンテーション違反の可能性はありません。C::s_AA::A()B

セグメンテーション違反が発生している場合は、別のことをしているに違いありません。定義の順番が違う?おそらく複数の翻訳単位ですか?実際のコードを投稿/説明します。

于 2010-04-14T20:02:10.847 に答える