c++ - 在 C++ 中,如何确保一个对象在另一个对象之前构造?

标签 c++ class object constructor

在 C++ 中,我们有两个全局对象,它们都是由其他人在不同的文件中定义的。一个对象的构建取决于另一个已经构建的对象。

class independent; 
class  dependent;
independent o1;
dependent o2;

为了确保 o1 在 o2 之前构造,我可以通过在 o2 之前声明 o1 来实现。

这可以确保 o1 在 o2 之前构建吗?如果编译器更改顺序怎么办?

谢谢

最佳答案

C++ 标准保证在同一编译单元内按顺序初始化静态变量,但在不同的编译单元中顺序未定义。这通常被称为“静态初始化顺序失败”

因此,如果您的变量在同一个 .cpp 中声明,它们会按照您声明它们的顺序进行初始化,如果它们在不同的文件中,您根本不知道(我见过非常积极的链接优化,无论情况如何,都会改变静态变量初始化的顺序,但这不符合标准,并且在正常用例中不应该发生。

核心问题

您的问题背后存在一个设计问题

  1. 如果您的一个类依赖于另一个类,那么它的结构应该明确地显示这种依赖性,并且不可能出现依赖性未满足的情况。

  2. 如果您有一个全局对象依赖于您无法明确控制的另一个对象,那么从属对象可能不应该是全局对象。

您的问题没有提供足够的细节来了解哪种设计最适合您,因此这里有一些建议供您做出决定。

依赖

那么首先,让我们表达这种依赖...

初始化时间依赖

dependent 的实例需要一个independent 的对象来初始化,但以后不再需要它。然后只需使默认构造函数不可访问并定义您自己的构造函数。

class dependent
{
  private:
    dependent(); // Implementation is optional

  public:
    dependent(const independent& sister)
    {
      // Initialize stuff
    }
}

终身依赖

dependent 类的实例在其整个生命周期内都需要一个independent 的对象,否则就没有意义。然后定义一个引用另一个对象的成员,再次使默认构造函数不可访问并定义您自己的构造函数。

class dependent
{
  private:
    dependent(); // No implementation

  public:
    dependent(const independent& sister): m_sister(sister)
    {
      // Initialize stuff
    }

    const independent& GetSister() const { return m_sister; }
    void SetSister(const independent& sister) { m_sister = sister; }

  private:
    const independent& m_sister;
}

失去依赖

dependent 的实例可能需要 independent 的对象才能工作,但没有对象仍然有意义。然后定义一个成员,它是指向另一个对象的指针。

class dependent
{
  public:
    dependent()
    {
      // Initialize stuff
    }

    const independent* GetSister() const { return m_sister; }
    void SetSister(const independent* sister) { m_sister = sister; }

  private:
    const independent* m_sister;
}

初始化顺序

现在让我们确保 independent 对象在 dependent 对象准备就绪时准备就绪。

初始化函数

您可以使用指针和 Init() 函数。

Independent* sister = NULL;
Dependent* brother = NULL;

Init()
{
    assert(brother == NULL && sister == NULL);
    sister = new independent();
    brother = new dependent(sister);
}

在使用中创建

您可以在函数中使用静态变量来强制执行创建顺序。这行得通,但拥有类的多个实例会很麻烦。

independent& GetSister()
{
    static independent sister; // Initialized on first use
    return sister;
}

dependent& GetBrother()
{
    static dependent brother(GetSister()); // Initialized on first use
    return brother;
}

没有全局变量

最后,最干净的方法可能是尝试完全摆脱全局变量。然后您将改用局部变量(您可以完全控制创建顺序)。当然你必须通过需要它们的函数来传递它,如果有很多,它会变得很麻烦。

但是当您识别出所有需要这些对象的代码时,将它移动到一个对象中可能是有意义的,并且您的两个原始全局变量将简单地成为该对象的成员。

class Foo
{
  public:
    Foo(): m_sister(...), m_brother(...)
    {
       // Initialize stuff
    }

    // Functions using the objects go here

  private:
    independent m_sister;
    dependent m_brother;
}

结论

嗯,我意识到我的回答很长,我有点忘乎所以了。这是要点:

  • 尽可能避免使用全局变量。
  • 表达类之间的依赖关系。
  • 不要犹豫,将代码和状态变量封装到一个类中,如果这会使事情变得更容易的话,它最终会有意义。

关于c++ - 在 C++ 中,如何确保一个对象在另一个对象之前构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18754212/

相关文章:

c++ - 分析磁盘访问

object - 在 Racket 中复制一个实例?

C++ 错误 LNK2019 && fatal error LNK1120 : 1 unresolved externals

c++ - 宽字符和 Windows 函数的 cpp 问题

php - 解析错误: syntax error, unexpected '$_POST' (T_VARIABLE) error and i just cant understand why?

java - Actionscript 覆盖扩展接口(interface)中的方法与 Java?

javascript - 遍历 javascript 对象和 valueOf toString 方法

python - 如何在 "decorator"对象中实现 "class"功能?

C++ 正则表达式,未知转义序列 '\.' 警告

c++ - Object b(); 有什么区别?和对象 b;?