我应该使用静态数据成员吗? (C++)
让我们考虑一个C++类。在执行开始时,我想从XML文件读取一组值,并将它们分配给该类的数据成员中的7个。这些值在整个执行过程中不会改变,它们必须由所讨论的类的所有对象/实例共享。静态数据成员是实现这种行为最优雅的方式吗? (当然,我不认为是全局变量)我应该使用静态数据成员吗? (C++)
听起来像一个很好的使用静态变量给我。您将这些参数用作固定参数而不是变量,并且这些值合法地需要共享。
正如其他人所说,在这种情况下使用静态成员似乎是适当的。请记住它不是万无一失的;全局数据的一些问题适用于静态成员:
- 您无法控制静态成员的初始化顺序,因此您需要确保没有全局变量或其他静态引用指向这些对象。有关更多详细信息,请参阅this C++ FAQ Question以及避免此问题的一些提示。
- 如果你在多线程环境中访问它们,你需要确保成员在你产生任何线程之前完全初始化。
听起来像是静态类成员的适当使用。只是不要忘记,它们是具有名称空间和(可能)一些保护的全局变量。因此,如果有可能您的应用程序有一天会演变成单独的“环境”或某些需要这些环境变量的东西,那么您已将自己绘制在一个角落。
按照Rob的建议,考虑使用一个单例,该单例稍后会变得更容易变成某种托管环境变量。
这不是一个干净的设计。静态类成员是全局状态和global state is bad。
它可能给你造成麻烦,如果这是一个小型到中型项目,你不具备自动测试高的目标,但既然你问:还有更好的方法。
一个更清洁的设计是为类创建一个工厂,并让工厂在构造它时将七个变量传递给类。 Factory的责任是确保所有实例共享相同的值。
这样,你的课就成为可测试的,你已经正确地区分了你的顾虑。
只要你认为可测试性的,你有另一种方式来设置静态变量,除了读入文件,再加上你不靠数据benig不变的过程中的整个执行时间 - 你应该精细。
我发现,当你设计你的代码编写测试思维可以帮助你保持代码的良好分解和可重复使用。
是的,静态数据成员就是你要找的。但是你必须注意你的静态变量的初始化/破坏顺序。 C++中没有任何机制可以确保您的静态变量在跨翻译单元使用之前被初始化。为了安全起见,使用看起来像单例模式的东西,并且知道解决这个问题。它的工作原理是:
- 所有静态对象都是在完成任何xml_stuff实例的构建之后完全构建的。
- 在C++中销毁静态对象的顺序与其构造完成相反(当它们的构造函数完成执行时)。
代码:
class xml_stuff {
public:
xml_stuff() {
// 1. touch all members once
// => 2. they are created before used
// => 3. they are created before the first xml_stuff instance
// => 4. they will be destructed after the last xml_stuff instance is
// destructed at program exit.
get_member1();
get_member2();
get_member3();
// ...
}
// the first time their respective function is called, these
// objects will be created and references to them are returned.
static type1 & get_member1() { static type1 t; return t; }
static type2 & get_member2() { static type2 t; return t; }
static type1 & get_member3() { static type1 t; return t; }
// ... all other 7 members
};
现在,get_memberN由xml_stuff返回的对象::()是任何xml_stuff实例的整个生命周期有效的,因为任何成员被任何xml_stuff实例之前建造的。使用纯静态数据成员,您无法确保,因为在C++中未定义跨翻译单元的创建顺序。
当时我想从一个 XML文件读出一组值,并将其分配到这个类的 数据成员的7开始执行。这些 值在执行整个 期间不会更改,并且它们必须由有问题的 类的所有对象/实例共享 。
黑体字的句子是这里的踢球者。只要该语句成立,静态变量的使用即可。这将如何执行?
很难。所以,如果您现在使用该声明总是如此,请继续。如果你想和未来的开发者(或你)一样使用错误的类(比如在程序中途读取另一个XML文件),那么就像Rasmus Farber所说的那样。
这些值是在执行开始时设置的,所以这些问题在这里并不适用。 – 2008-12-23 20:54:02
大卫,他们会一旦决定将xml对象作为静态对象放置在某处。销毁的顺序也是相关的。请参阅下面的答案。 – 2008-12-23 23:23:09