简体   繁体   English

在C ++中调用静态成员对象的函数

[英]Calling functions of a static member object in C++

I'm not sure I've used the right terminology in my title, but here's what I'm trying to do: 我不确定我在标题中使用了正确的术语,但是这是我想要做的:

I have a lightweight particle class (simplified) that requires random behavior for birth and wall-collision. 我有一个轻量级粒子类(简化),该类需要随机行为来进行出生和墙体碰撞。 I'd like to keep the facilities for that in the class itself. 我想在课堂上保留用于此目的的设施。 To my understanding a static member is created only once and can be shared among all instances of the class. 据我了解,静态成员仅创建一次,并且可以在该类的所有实例之间共享。

For the random number generator object, I would like to call the seed method once, but am unsure how to do this, as most examples use plain static variables or functions. 对于随机数生成器对象,我想调用一次seed方法,但是不确定如何执行此操作,因为大多数示例都使用纯静态变量或函数。

Particle.h: Particle.h:

#include <random>

class Particle
{
    public:
        Particle();
    private:
        static std::default_random_engine pRNG;
        static std::uniform_real_distribution<> dist(0, 1);
};

Particle.cpp 粒子

#include "particle.h"
#include <ctime>

std::default_random_engine Particle::pRNG.seed(time(NULL)); // <- wrong, help!

Particle::Particle() {}

// methods, etc.

Putting the seed method into the Particle constructor would call it on every born particle I suppose. 种子方法放入“粒子”构造函数将在我假设的每个出生粒子上调用它。 The only quick hack I could think of was to add a bool member to the Particle class, that is set to false on the first seed call. 我能想到的唯一快速的技巧是将一个bool成员添加到Particle类,在第一个种子调用时将其设置为false。

Simple way to do this: Make a class called "AutoInitRNG", which seeds the default_random_engine in its constructor. 执行此操作的简单方法:制作一个名为“ AutoInitRNG”的类,该类将default_random_engine植入其构造函数中。 And make that class a static member variable of Particle. 并使该类成为粒子的静态成员变量。 Something like this: 像这样:

class AutoInitRNG
{
public:
    std::default_random_engine pRNG;

    AutoInitRNG()
    {
        pRNG.seed(time(NULL));
    }
};

class Particle
{
//...
private:
    static AutoInitRNG RNG;
};

std::default_random_engine Particle::pRNG.seed(time(NULL)); std :: default_random_engine粒子:: pRNG.seed(time(NULL)); // <- wrong, help! // <-错误,请帮助!

This is perfectly fine, except that its in the wrong place. 这样做很好,除了错误的地方。 it should be inside a code block, context of some kind. 它应该在代码块内,某种上下文中。 I suggest to separate this facility to a singleton class, that would be called for random number. 我建议将此功能分为单例类,这将被称为随机数。 Otherwise, you'll have to call it from outside the class somewhere. 否则,您将不得不从类之外的某个地方调用它。

Calling it in a constructor will lead to multiple calls, that's not what you want, or if you want to call it from within a class - add a static flag to mark that it has been seeded to make sure you only call it once. 在构造函数中调用它会导致多次调用,这不是您想要的,或者如果您想从一个类中调用它,请添加一个静态标志以标记它已被植入以确保仅调用一次。

You want to call seed after the construction of Particle::pRNG , and exactly once. 您要在构建Particle::pRNG之后调用seed ,并且只调用一次。 Anything with static storage duration is initialized exactly once. 具有静态存储持续时间的所有内容都将被初始化一次。 And if two definitions with static storage duration and dynamic initialization are in the same translation unit, they'll always be initialized in that order (and destroyed in the reverse order). 并且,如果具有静态存储持续时间和动态初始化的两个定义位于同一转换单元中,则它们将始终以该顺序进行初始化(并以相反的顺序销毁)。

So all you need is a second definition. 因此,您所需要的只是第二个定义。 The trick is making up something just so you can define it. 诀窍是组成一些东西,以便您可以定义它。

// In header:
class Particle {
    // ...
private:
    static std::default_random_engine pRNG;
    class RNG_Setup_;
    friend class Particle::RNG_Setup_;
};

// In source:
std::default_random_engine Particle::pRNG;
class Particle::RNG_Setup_ {
    RNG_Setup_() { Particle::pRNG.seed(time(nullptr)); }
    static RNG_Setup_ setup_instance;
};
Particle::RNG_Setup_::setup_instance{};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM