use*_*472 2 c++ constructor class object
在C++中,我们有两个全局对象,它们都由不同文件中的其他对象定义.一个物体的构造取决于已经构建的另一个物体.
class independent;
class dependent;
independent o1;
dependent o2;
Run Code Online (Sandbox Code Playgroud)
为了确保在o2之前构造o1,我可以通过在o2之前声明o1来实现.
这可以确保o1是在o2之前建造的吗?如果编译器改变了odering怎么办?
谢谢
C++标准保证在同一编译单元中初始化静态变量,但在单独的编译单元中未定义顺序.这通常被称为"静态初始化顺序惨败".
因此,如果您的变量在同一个.cpp中声明,它们会按照您声明的顺序进行初始化,如果它们位于不同的文件中,您根本就不知道(我已经看到非常激进的链接优化的情况)这改变了静态变量初始化的顺序,无论情况如何,但这不符合标准,并且不应该在正常使用情况下发生).
你的问题背后隐藏着一个设计问题.
如果你的一个类依赖于另一个类,那么它的结构应该明确地显示这个依赖关系,并且不可能进入不满足依赖性的情况.
如果你有一个全局对象依赖于你无法控制的另一个全局对象,那么从属对象可能不应该是全局对象.
您的问题没有提供足够的详细信息来了解哪种设计最适合您,因此这里有一些您可以做出决定的建议.
首先,让我们表达这种依赖......
类的实例dependent需要一个independent初始化对象,但以后不再需要它.然后只是使默认构造函数不可访问并定义自己的构造函数.
class dependent
{
private:
dependent(); // Implementation is optional
public:
dependent(const independent& sister)
{
// Initialize stuff
}
}
Run Code Online (Sandbox Code Playgroud)
类的实例在其生命周期中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;
}
Run Code Online (Sandbox Code Playgroud)
类的实例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;
}
Run Code Online (Sandbox Code Playgroud)
现在让我们确保independent对象准备就绪dependent.
你可以使用指针和Init()函数.
Independent* sister = NULL;
Dependent* brother = NULL;
Init()
{
assert(brother == NULL && sister == NULL);
sister = new independent();
brother = new dependent(sister);
}
Run Code Online (Sandbox Code Playgroud)
您可以在函数中使用静态变量来强制执行创建顺序.这有效,但是让几个类的实例变得很麻烦.
independent& GetSister()
{
static independent sister; // Initialized on first use
return sister;
}
dependent& GetBrother()
{
static dependent brother(GetSister()); // Initialized on first use
return brother;
}
Run Code Online (Sandbox Code Playgroud)
最后,最干净的方法可能是试图完全摆脱全局变量.然后,您将使用局部变量(您可以完全控制创建顺序).当然你必须通过需要它们的函数传递它,如果有很多它们,它会变得很麻烦.
但是当你确定需要这些对象的所有代码时,在对象中移动它可能是有意义的,并且你的两个原始全局变量将简单地成为该对象的成员.
class Foo
{
public:
Foo(): m_sister(...), m_brother(...)
{
// Initialize stuff
}
// Functions using the objects go here
private:
independent m_sister;
dependent m_brother;
}
Run Code Online (Sandbox Code Playgroud)
嗯,我意识到我的答案很长,我有点沮丧.这是外卖:
如果在编译单元中有两个全局变量,那么它们将按顺序初始化.如果它们在不同的编译单元中处于不同的顺序(就像它们在由不同的.cpp包含在不同顺序中的不同.h文件中),则结果是未定义的.
如果您必须按顺序排列它们,但无法将它们放在同一个补偿单元中,请考虑使用单例模式.
class Independent
{
public:
static Independent& getO1()
{
static Independent o1;
return o1;
}
};
class Dependent
{
public:
static Dependent& getO2()
{
Independent::getO1(); // force o1 to exist first
static Dependent o2;
return o2;
}
};
Run Code Online (Sandbox Code Playgroud)
这使用静态局部变量在首次使用时初始化的规则,以确保顺序,无论.h文件如何包含在内.