2011-04-21 45 views
0

我想提出一个简单的Random类使用随机类:以静态方式

class Random 
{ 
public: 
    static bool seeded = false; 

    static void SeedRandom(int number) 
    { 
     srand(number); 
    } 
    static int GetRandom(int low, int high) 
    { 
     if (!seeded) 
     { 
      srand ((int)time(NULL)); 
     } 
     return (rand() % (high - low)) + low; 
    } 
}; 

显然C++不允许一整类被声明为static(这是什么使这很容易在C# )。我改为让所有成员为static。也没有static的构造函数,所以我没有办法初始化我的bool seeded,除非我手动调用一个函数,这会破坏目的。我可以改为使用一个常规的构造函数,在这个构造函数中我将不得不创建一个Random的实例,我不想这样做。

此外,有没有人知道如果新的C++ 0x标准将允许静态类和/或静态构造函数?

+0

你班里的'bool seeded = false'位无效。只有静态的** const ** intergal成员可以用这种方式在类的主体中初始化。您必须单独声明“种子”并在声明点(而不是定义点)对其进行初始化。 – 2011-04-21 07:46:49

回答

6

C++不允许声明全班静态

当然它中。

class RandomClass 
{ 
public: 
    RandomClass() 
    { 
     srand(time(0)); 
    } 
    int NextInt(int high, int low) 
    { 
     return (rand() % (high - low)) + low; 
    } 
} 

RandomClass Random; //Global variable "Random" has static storage duration 

//C# needs to explicitly allow this somehow because C# does not have global variables, 
//which is why it allows applying the static keyword to a class. But this is not C#, 
//and we have globals here. ;) 

真的,虽然没有理由把它放在课堂上。 C++不会强迫你将所有东西都放在类中 - 这是很好的理由。在C#中,你不得不把所有东西都放到一个类中,并用静态方法等声明事物,但是这不是意识形态C++

你真的不能只考虑意识形态的C#代码,并用C++编写代码,并期望它运行良好。它们是非常不同的语言,具有非常不同的要求和编程特征。

如果你想要一个意识到的C++方式来做到这一点,不要做任何类。呼叫srandmain内,并定义,做你的夹紧功能:

int RandomInteger(int high, int low) 
{ 
    return (std::rand() % (high - low)) + low; 
} 

编辑:当然,这将是更好地为您使用新的随机数生成工具和uniform_int_distribution让你的夹持范围而不是rand。请参阅rand() considered harmful

+0

要说随机变量具有静态存储对于C++并不完全准确。如上所述,它是一个全局变量(这可能是需要的)。一个静态变量在它定义的模块中具有局部范围。 – Blazes 2011-04-21 08:14:36

+2

@Blazes:全局变量在C++中有静态存储持续时间。 C++定义了3个存储持续时间(好吧,C++ 11中增加了'线程'存储持续时间):'自动'(“堆栈分配”变量),'静态'(全局变量和本地'静态'变量)动态'(分配'malloc'或'new')。自动变量一直存在直到它们的块结束,动态变量一直存在直到它们被调用“delete”或“free”,并且静态变量一直存在直到程序终止。 – 2011-04-21 08:18:43

+1

@Blazes:要清楚,静态存储的持续时间有**没有什么**与静态关键字。 (在我的标准副本第3.7节中有详细说明...) – 2011-04-21 08:19:39

2

您的static bool seeded无论如何都需要在cpp文件中定义,您必须在那里初始化它。

bool Random::seeded = false; 
0

试试这个:

class Random 
{ 
public: 
    static bool seeded; 

    static void SeedRandom(int number) 
    { 
     srand(number); 
     seeded = true; 
    } 

    static int GetRandom(int low, int high) 
    { 
     if (!seeded) 
      SeedRandom(time(0)); 
     return (rand() % (high - low)) + low; 
    } 
}; 

bool Random::seeded; 

staticbool小号得到默认初始化为false,所以没有必要做这样明确。请注意,您的实际班级逻辑也是错误的,因为您从未将seeded设置为true

+0

这是一个很好的类,但你错了Random :: seeded被默认初始化为'false'。在调试模式下,它将被设置为“假”,但在发布时,除非特别初始化,否则它将具有随机值。始终初始化成员变量。 – Blazes 2011-04-21 08:18:20

+2

@Blazes:'seeded'不是一个成员变量,它是'static'。从C++ 03标准§9.4.2/ 7开始:“*静态数据成员与非本地对象(3.6.2,3.6.3)。*”一样被初始化和销毁​​。从§3.6.2/ 1:“具有静态存储时间(3.7.1)*标的应当是任何其他初始化 发生之前初始化为零(8.5)*”所以,'seeded'将永远** **是零初始化,对于“布尔”当然意味着“假” - 标准要求它。 – ildjarn 2011-04-21 08:22:30

+1

为什么当一切都是公共和静态的时候,使它成为一个类而不是一个名称空间?有时答案是“我如何做到这一点?”是“不要那样做!”。 (“医生,医生 - 当我这样做时会感到痛苦!”)。 – 2011-04-21 08:44:48

0

你总是可以用singleton模式来解决这个问题,通过让构造函数为private和对象的静态存取器。


class Random 
{ 
public: 
    static Random& instance() 
    { 
    static Random instance; 

    return instance; 
    } 

    // your other functions here 

private: 
    Random() 
    { 
    // your seed code here 
    }  
}; 

这将确保你只有类的一个实例,每当你需要一个随机的,你只需要调用随机::实例()。()函数

+2

看不到很多理由为另一个单例(std :: rand/std :: srand)创建一个单例(你的类Random)。 – 2011-04-21 07:43:29

+0

同样的逻辑也可以作为被应用到为什么在所有使用另一个类,它只是提供了一个实例全局访问的包装,可与任何功能的用户的需求进行扩展。 – 2011-04-21 07:51:12

+0

我会争辩说,不应该在这里使用另一个班级。 C++并不需要所有的东西都在一个类中。这种编程方式并没有有效地使用该语言。 – 2011-04-21 07:52:50

0

什么是你的原因有静态方法的类?可能有一个替代方案来实现你的目标。你在找单独的东西吗?

顺便说一句,如果你有静态成员变量的类声明,正如我之前其他的答案中指出,必须初始化它们的类(最好是在cpp文件)外使用它们之前。因此,如果你按照这样做,并初始化你的想法:

bool Random::seeded = false
它会自动初始化为false,如你所愿。

1

你不必让一切在C++的类。

namespace Random 
{ 
    bool seeded = false; 

    void SeedRandom(int number) 
    { srand(number); } 

    int GetRandom(int low, int high) 
    {   
     if (!seeded) 
     { srand((int)time(NULL)); } 

     return (rand() % (high - low)) + low; 
    }  

}