0

我知道下面的代码会导致分段错误,因为在 A 的 cstr 处,B::SYMBOL 尚未初始化。但为什么?

实际上,A 是一个用作映射的对象,它将像 B 这样的类的符号映射到它们各自的 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

如果您交换 and 的定义AB那么代码应该可以编译并正常工作。只要一切都在同一个翻译单元中,初始化顺序就不应该有任何问题,假设静态成员的定义. 在同一个翻译单元中定义的对象按照它们的定义顺序进行初始化,这意味着在开始的时候,静态成员已经被初始化了。在这种情况下,没有出现分段错误的可能性。BC::s_AA::A()B

如果您遇到分段错误,则您必须采取不同的措施。定义顺序不同?可能有多个翻译单元?发布/描述真实代码。

于 2010-04-14T20:02:10.847 回答