2013-10-29 154 views
0

我正在製作一個類似於Minecraft的遊戲,其中所有各種塊都由.h文件中的單個static const Block <name>;表示。我將它們作爲const Block Block::<name> = Block("name", 0, 0);在.cpp文件中初始化,並在構造函數中傳遞它使用的紋理的索引(表示爲無符號字符)。在構造函數中,它設置了索引變量,但是當我稍後在程序中嘗試調用它時,它會返回完全不同的值。靜態const對象不是保留值

這裏是重要的部分:

Block::Block(std::string name, uint16 id, uint8 tex) 
{ 
    //Check for repeat ids 
    if (IdInUse(id)) 
    { 
     fprintf(stderr, "Block id %u is already in use!", (uint32)id); 
     throw std::runtime_error("You cannot reuse block ids!"); 
    } 
    _id = id; 
    idMap.insert(std::make_pair(id, *this)); 
    //Check for repeat names 
    if (NameInUse(name)) 
    { 
     fprintf(stderr, "Block name %s is already in use!", name); 
     throw std::runtime_error("You cannot reuse block names!"); 
    } 
    _name = name; 
    nameMap.insert(std::make_pair(name, *this)); 

    _tex = tex; 
    fprintf(stdout, "Using texture %u\n", _tex); 

    _transparent = false; 
} 

uint8 Block::GetIndex() const 
{ 
    fprintf(stdout, "Returning texture %u\n", _tex); 
    return _tex; 
} 

我傳遞0到構造函數中tex,並打印作業打印後_tex出0,所以我知道它是越來越在構造函數中正確設置。但是,稍後當程序調用GetIndex()時,由於某種原因它總是返回204。我不知道它爲什麼這樣做,但我認爲這可能與我宣佈所有塊爲static const的事實有關。另外,我知道_tex的值沒有被更改,因爲對象是const,並且Block在初始化後沒有以任何方式操作。

如果有人知道什麼可能導致此,任何幫助非常感謝。

編輯:

在Block.h,這是聲明塊中的線,內class Block摘自:

public: 
    static const Block Test; 

然後在Block.cpp,這是朝向頂部的線該文件的:

const Block Block::Test = Block("Test", 1, 0); 

這裏是block.h,和block.cpp整體。

+1

使用顯示您的靜態對象的實際申報的模式。還有初始化器的定義。 – AnT

+0

@AndreyT我編輯的帖子包括你在找什麼。 – sm81095

+0

你有沒有在你的課堂上有用戶定義的複製構造函數? – AnT

回答

1

問題是構造對象被放置在idMapnameMap之內的是被構造對象的拷貝 - 在_tex被初始化之前。

請注意,同樣的問題適用於_name成員(至少對於idMap集合)和_transparent成員。

因此,當您從其中一個集合中查找對象時,您將檢索到不完美的副本。

您應該在將其添加到集合之前完全構造該對象。讓地圖存儲指向對象的指針而不是副本也許更有意義。如果您不打算複製這些Block對象,則還應禁用複製和分配構造函數。

+0

這完全解決了我的問題,謝謝。我仍然是C++的新手(因此對於指針等),所以我自己從來沒有發現過。我還更改了映射以保存指針引用,並禁用了複製和賦值構造函數。再次,非常感謝。 – sm81095

+0

雖然刪除複製構造函數現在使行'const Block Block :: Test = Block(「Test」,1,0);'給出錯誤:「錯誤:函數'Block :: Block(const Block&)'不能引用 - 它是一個刪除的函數。「令人困惑的是,考慮到我沒有在該行中使用複製構造函數。 – sm81095

+0

它現在還告訴我'Block(const Block&)= delete;'和Block&operator =(const Block&)= delete;'在語法上是無效的。我絕對使用C++ 11,因爲我使用VS2012,並且在我的代碼中廣泛使用了'nullptr'。 – sm81095

0

由於您沒有在此處發佈足夠但至關重要的代碼部分(特別是Block類的聲明),因此您實際嘗試執行的操作有點不清楚。

您的陳述static const Block <name>;似乎意味着模板聲明,其中需要在模板標頭中定義靜態成員實例,而在單獨的.cpp文件中定義而不是。但如果是這樣,我不相信你的示例代碼會按原樣編譯。

1

我看不到idMap的定義,但它很清楚std::map<uint16, Block>。這意味着它包含您的Block的副本。 當你把你的結構到地圖中通過調用拷貝constructor->idMap.insert(std::make_pair(id, *this));

請注意,您設置的_tex變量之前,所以新的副本具有隨機_tex值發生這種情況時會創建一個新的模塊。

您不應將指針傳遞給塊。這會在Block超出範圍並被清理的時候造成segementation故障。

你真的應該去了解和使用boost ::輕量級這是你正試圖在這裏

+0

我接受了其他答案,但這個也說了同樣的事情。所以謝謝你的回答。 – sm81095