我应该使用静态数据成员吗? (C ++)

时间:2008-12-23 19:07:23

标签: c++ variables static static-members

让我们考虑一个C ++类。在执行开始时,我想从XML文件中读取一组值,并将它们分配给该类的7个数据成员。这些值在整个执行期间不会改变,并且它们必须由所讨论的类的所有对象/实例共享。静态数据成员是实现此行为的最佳方式吗? (当然,我不考虑全局变量)

8 个答案:

答案 0 :(得分:5)

正如其他人所提到的,在这种情况下使用静态成员似乎是合适的。请记住,这不是万无一失的;全局数据的一些问题适用于静态成员:

  • 您无法控制静态成员的初始化顺序,因此您需要确保没有全局变量或其他静态参考这些对象。有关详细信息,请参阅this C++ FAQ Question以及有关避免此问题的一些提示。
  • 如果您在多线程环境中访问它们,则需要确保在生成任何线程之前完全初始化成员。

答案 1 :(得分:3)

听起来像是对我使用静态变量。您将这些更多地用作固定参数而不是变量,并且合法地需要共享这些值。

答案 2 :(得分:3)

静态成员可以在这里工作,完全可以接受。另一个选择是对包含这些成员的类使用singleton pattern,以确保它们只被构造/设置一次。

答案 3 :(得分:3)

这不是一个干净的设计。静态类成员是全局状态和global state is bad

如果这是一个中小型项目并且你没有很高的自动测试目标,那么它可能不会给你带来麻烦,但是因为你问:有更好的方法。

更简洁的设计是为类创建一个Factory,并让Factory在构造它时将七个变量传递给类。然后,工厂负责确保所有实例共享相同的值。

通过这种方式,您的课程变得可以测试,并且您已经正确地分离了您的问题。

PS。 Don't use singletons either

答案 4 :(得分:2)

听起来像是对静态类成员的恰当使用。只是不要忘记它们实际上是具有命名空间和(可能)某种保护的全局变量。因此,如果您的应用程序有可能在某一天发展出单独的“环境”或者每个需要一组这些全局变量的东西,那么您就已经将自己画成了一个角落。

如Rob建议的那样,考虑使用单例,稍后更容易将其转换为某种托管环境变量。

答案 5 :(得分:2)

  

在执行开始时,我想从一个读取一组值   XML文件并将它们分配给7个   此类的数据成员。那些   价值观在整体上不会改变   执行,他们必须共享   由所有的对象/实例   有问题的课程。

粗体句是这里的踢球者。只要该语句成立,静态变量的使用就可以了。这将如何执行?

这很难。所以,如果您现在使用的声明始终是真的,请继续。如果你希望某个未来的开发人员(或你)使用你的类错误(比如在程序中间读取另一个XML文件),那么就像Rasmus Farber所说的那样。

答案 6 :(得分:1)

是的,静态数据库就是你要找的东西。但是你必须注意静态变量的初始化/销毁顺序。在您使用翻译单元之前,C ++中没有任何机制可以确保您的静态变量已初始化。为了安全起见,使用看似单身模式的东西,众所周知可以解决这个问题。它的工作原因是:

  1. 在完成任何xml_stuff实例的构建之后,完全构造所有静态对象。
  2. 在C ++中销毁静态对象的顺序与它们构造的完成完全相反(当它们的构造函数完成执行时)。
  3. 代码:

    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
    };
    

    现在,xml_stuff :: get_memberN()返回的对象在任何xml_stuff实例的整个生命周期内都是有效的,因为任何这些成员都是在任何xml_stuff实例之前构造的。使用纯静态数据成员,您无法确保,因为在C ++中未定义跨翻译单元的创建顺序。

答案 7 :(得分:0)

只要你想到可测试性并且除了在文件中读取之外你还有另一种设置静态变量的方法,而且你不需要在整个过程执行时间内保持数据不变 - 你应该没问题

我发现在设计代码时考虑编写测试可以帮助您保持代码的良好分解和可重用性。