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

发布于 2024-07-10 22:31:42 字数 139 浏览 6 评论 0原文

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

Let's consider a C++ class. At the beginning of the execution I want to read a set of values from an XML file and assign them to 7 of the data members of this class. Those values do not change during the whole execution and they have to be shared by all the objects / instances of the class in question. Are static data members the most elegant way to achieve this behavior? (Of course, I do not consider global variables)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

╰沐子 2024-07-17 22:31:42

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

  • 您无法​​控制静态成员的初始化顺序,因此您需要确保没有全局变量或其他静态变量引用这些对象。 有关更多详细信息,请参阅此 C++ 常见问题解答了解一些避免此问题的提示。
  • 如果您在多线程环境中访问这些成员,您需要确保在生成任何线程之前成员已完全初始化。

As others have mentioned, the use of static members in this case seems appropriate. Just remember that it is not foolproof; some of the issues with global data apply to static members:

  • You cannot control the order of initialization of your static members, so you need to make sure that no globals or other statics refer to these objects. See this C++ FAQ Question for more details and also for some tips for avoiding this problem.
  • If your accessing these in a multi-threaded environment you need to make sure that the members are fully initialized before you spawn any threads.
冷情妓 2024-07-17 22:31:42

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

Sounds like a good use of static variables to me. You're using these more as fixed parameters than variables, and the values legitimately need to be shared.

太阳男子 2024-07-17 22:31:42

静态成员可以在这里工作并且完全可以接受。 另一种选择是对保存这些成员的类使用 单例模式,以确保它们是仅构造/设置一次。

static members would work here and are perfectly acceptable. Another option is to use a singleton pattern for the class that holds these members to ensure that they are constructed/set only once.

蘸点软妹酱 2024-07-17 22:31:42

这不是一个干净的设计。 静态类成员是全局状态,全局状态不好。

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

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

这样你的类就变得可测试,并且你已经正确地分离了你的关注点。

附言。 不要 使用 单例 要么

It is not a clean design. Static class members are global state and global state is bad.

It might not cause you trouble if this is a small- to medium-sized project and you do not have high goals for automatic testing, but since you ask: there are better ways.

A cleaner design would be to create a Factory for the class and have the Factory pass your seven variables to the class when it constructs it. It is then the Factory's responsility to ensure that all instances share the same values.

That way your class becomes testable and you have properly separated your concerns.

PS. Don't use singletons either.

眼藏柔 2024-07-17 22:31:42

听起来像是静态类成员的适当使用。 只是不要忘记它们实际上是具有命名空间和(也许)一些保护的全局变量。 因此,如果您的应用程序有一天可能会发展出单独的“环境”,或者每个环境都需要一组这样的全局变量,那么您就会把自己逼入绝境。

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

sounds like an appropriate use of static class members. just don't forget that they're really global variables with a namespace and (maybe) some protection. therefore, if there's the possibility that your application could someday evolve separate 'environments' or something that would need a set of these globals for each, you'd have painted yourself into a corner.

as suggested by Rob, consider using a singleton, which is easier to turn later into some kind of managed environment variable.

情归归情 2024-07-17 22:31:42

在执行开始时,我想从
XML 文件
并将它们分配给其中的 7 个
该类的数据成员。 那些
整个过程中值不会改变
执行并且必须共享
由所有对象/实例
有问题的类。

粗体字的句子是这里的关键。 只要该声明成立,就可以使用静态变量。 这将如何执行?

很难。 因此,如果您现在可以使用该陈述,那么就继续吧。 如果您希望未来的开发人员(或您)使用错误的类(例如在程序中途读取另一个 XML 文件),那么请执行 Rasmus Farber 所说的操作。

At the beginning of the execution I want to read a set of values from an
XML file
and assign them to 7 of the
data members of this class. Those
values do not change during the whole
execution and they have to be shared
by all the objects / instances of the
class in question.

The sentence in boldface is the kicker here. As long as that statement holds, the use of static variables is OK. How will this be enforced?

It's hard to. So, if for your use right now the statement is always true, go ahead. If you want to be same from some future developer (or you) using your classes wrong (like reading another XML file midway in the program), then do something like what Rasmus Farber says.

一指流沙 2024-07-17 22:31:42

是的,静态数据成员就是您所寻找的。 但是您必须注意静态变量的初始化/销毁顺序。 C++ 中没有机制可以确保静态变量在跨翻译单元使用之前已初始化。 为了安全起见,请使用看起来像单例模式的模式,众所周知,它可以解决该问题。 它之所以有效,是因为:

  1. 所有静态对象都是在任何 xml_stuff 实例完全构造之后才完全构造的。
  2. 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
};

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

Yes, static datamembers are what you look for. But you have to take care for the initialization/destruction order of your static variables. There is no mechanism in C++ to ensure that your static variables are initialized before you use them across translation units. To be safe, use what looks like the singleton pattern and is well known to fix that issue. It works because:

  1. All static objects are completely constructed after the complete construction of any xml_stuff instance.
  2. The order of destruction of static objects in C++ is the exact opposite of the completion of their construction (when their constructor finishes execution).

Code:

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

Now, the objects returned by xml_stuff::get_memberN() are valid the whole lifetime of any xml_stuff instance, because any of those members were constructed before any xml_stuff instance. Using plain static data members, you cannot ensure that, because order of creation across translation units is left undefined in C++.

不语却知心 2024-07-17 22:31:42

只要您考虑到可测试性,并且除了读入文件之外,您还有另一种方法来设置静态变量,而且您不依赖于在进程的整个执行时间内保持不变的数据 - 您应该没问题。

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

As long as you think of testability and you have another way to set the static variables besides reading in a file, plus you don't rely on the data benig unchanged for the entire execution time of the process - you should be fine.

I've found that thinking of writing tests when you design your code helps you keep the code well-factored and reusable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文