2011-04-21 80 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; 
    }  

} 
相關問題