在 C++ 中,我们有两个全局对象,它们都是由其他人在不同的文件中定义的。一个对象的构建取决于另一个已经构建的对象。
class independent;
class dependent;
independent o1;
dependent o2;
为了确保 o1 在 o2 之前构造,我可以通过在 o2 之前声明 o1 来实现。
这可以确保 o1 在 o2 之前构建吗?如果编译器更改顺序怎么办?
谢谢
最佳答案
C++ 标准保证在同一编译单元内按顺序初始化静态变量,但在不同的编译单元中顺序未定义。这通常被称为“静态初始化顺序失败”。
因此,如果您的变量在同一个 .cpp 中声明,它们会按照您声明它们的顺序进行初始化,如果它们在不同的文件中,您根本不知道(我见过非常积极的链接优化,无论情况如何,都会改变静态变量初始化的顺序,但这不符合标准,并且在正常用例中不应该发生。
核心问题
您的问题背后存在一个设计问题。
如果您的一个类依赖于另一个类,那么它的结构应该明确地显示这种依赖性,并且不可能出现依赖性未满足的情况。
如果您有一个全局对象依赖于您无法明确控制的另一个对象,那么从属对象可能不应该是全局对象。
您的问题没有提供足够的细节来了解哪种设计最适合您,因此这里有一些建议供您做出决定。
依赖
那么首先,让我们表达这种依赖...
初始化时间依赖
类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/