2010-07-20 130 views
1

静态成员有时会让我困惑。我已经知道如何初始化内建类型,例如int沿的int myClass::statVar = 10;线,您在.cpp文件放置的东西简单,但我有以下类似的东西:对象静态成员的初始化

class myClass 
{ 
public: 
// Some methods... 

protected: 
static RandomGenerator itsGenerator; 
} 

的基本思想是足够简单:myClass需要访问它的一个成员函数的随机生成器。由于每个对象都相当大,我也只能拥有少数几个发生器实例。但是,RandomGenerator类型需要“初始化”,可以这么说,通过调用RandomGenerator::Randomize(),编译器不允许你这么做,因为它不是一个const rvalue(是吗?)。

那么我该如何做这项工作?

或者在这种情况下,我应该不使用静态变量,并以其他方式做?

回答

2

您可以创建包装类,它将包含RandomGenerator实例,并将在其构造函数中调用RandomGenerator::Randomize

+0

这是坏的。外部类不应该知道发生器的存在。你只改变了它的方式。这是一种解决方法,但它不是解决方案。 – Gangnus 2011-12-19 07:59:43

+0

@Gangnus:不一定。封装一切都很好,但从外部提供策略没有任何问题,特别是如果您有可能将更多的责任归咎于现有的外部类别。 – 2013-08-13 13:51:48

2

把它放在一个私人字段中,公开一个静态存取器。在访问器中,如果成员尚未初始化,则对其进行初始化。

+0

我正朝着这个方法努力。我认为这可能是更好的解决方案,虽然包装发电机也似乎是一个优雅的想法。 – 2010-07-20 10:16:05

+0

这是坏的。外部类不应该知道发生器的存在。你只改变了它的方式。这是一种解决方法,但它不是解决方案。 – Gangnus 2011-12-19 08:27:15

1

在这些情况下,单身人士实际上是你的朋友,尽管他们还有其他缺点。

+0

是的。我担心,在C++中它是唯一真正正确的方法。任何来自外太空的深层内部私人领域的设置都是不正确的。外围空间不应该知道内部发生器及其初始化。 – Gangnus 2011-12-19 07:57:15

+0

@Gangus:查看我的其他评论。这不一定是真的。有时可以从外部提供策略。查看标准库 - 您可以将分配类型作为模板参数提供给基本上所有的容器类型,这是完全正确的。 – 2013-08-13 13:52:36

0

它只是一个需要使用RandomGenerator的函数吗?你可以这样做了这种方式:

INT MyClass的:: foo的(){ 静态 RandomGenerator itsGenerator = RandomGenerator ::随机化() ... }

+0

这不起作用,因为Randomize不返回生成器。分隔线会导致发生器在您每次输入块时被随机化。 – 2010-07-20 10:17:24

1

如果RandomGenerator是可复制,可使用用于初始化的辅助函数:

RandomGenerator init_rg() { 
    RandomGenerator rg; 
    rg.Randomize(); 
    return rg; 
} 

RandomGenerator myClass::itsGenerator = init_rg(); 
+0

初始化全局(静态)变量时要小心,因为不能保证排序。 – doron 2010-07-20 11:24:23

1

只写其返回引用到适当的随机RandomGenerator功能,把itsGenerator为参考发电机:

class myClass 
{ 
public: 
// Some methods... 

protected: 
// make this a reference to the real generator 
static RandomGenerator& itsGenerator; 
public: 
static RandomGenerator& make_a_generator() 
{ 
    RandomGenerator *g=0; 
    g=new RandomGenerator(); 
    g->Randomize(); 
    return *g; 
} 
} 

RandomGenerator& myClass::itsGenerator=myClass::make_a_generator(); 
+0

为什么这么复杂,如果你只能返回一个堆栈分配的实例,让NRVO负责其余的部分或者使用一个函数本地'静态'实例? – 2010-07-20 10:50:12

+0

即使使用NRVO,RandomGenerator也需要一个可访问的拷贝构造函数。我只是想避免不必要的要求。 – 2010-07-20 10:57:39

0

如果只有myClass需要RandomGenerator,则:

myClass::myClass() 
{ 
    itsGenerator.Randomize(); 
} 

不要紧,如果你重新随机的随机数生成器为每个对象?我假设没有;-)