2013-08-19 32 views
0
class GameBoy{ 

    public: 
    GameBoy() 
     :cart(new Cartridge()), 
     mmu(new MMU(cart)), 
     cpu(new CPU(mmu)) 
    {} 

    void step(); //steps through one instruction 
    const CPU::State &getCPUState() const noexcept; 
    void loadROM(std::string fileName); 

    private: 
    std::shared_ptr<Cartridge> cart; 
    std::shared_ptr<MMU> mmu; 
    std::shared_ptr<CPU> cpu; 

    }; 

我正在寫一個Game Boy模擬器,這個類是Qt GUI將與之交互的。也就是說,對於在GUI中繪製的每個幀,它將調用GameBoy :: step()。顯然,由於我還沒有開始在GPU上工作,所以沒有完成。單身人士,shared_ptr,原始指針或其他指針?

我目前在質疑這個設計,因爲這3個類(Cartridge,CPU,MMU)只會被實例化一次。單身人士是否會比這更好的設計,還是現在的設計最好?

如果這一個是最好的,我應該留在shared_ptr?我已經讀過,它應該謹慎使用,但在這裏,這似乎是有道理的,因爲所有3個類互相依賴。

非常感謝!

編輯:人們問我爲什麼我使用指針。從init列表中可以看到,MMU需要對Cartridge的引用,CPU需要引用MMU。

Cartridge將被GameBoy :: loadROM()和大多數MMU方法使用。我同意MMU可能不需要由GameBoy擁有,但它將在CPU和GPU之間共享(我認爲)。

在下面的示例中,是否有更好的替代購物車共享指針?課間

用法示例:

byte MMU::readByte(word address) { 
      .... 
      value = cart->readROM(address); 
      .... 
     } 

void GameBoy::loadROM(std::string fileName){ 
      cart->loadROM(fileName); 
} 

編輯2:謝謝大家!我有一個最後的問題。如果GPU和CPU都使用了MMU和GameBoy的同時使用GPU和CPU,它的設計是更好:

class GameBoy{ 

public: 
GameBoy() 
: CPU(&mmu), gpu(&mmu) 
... 

private: 
MMU mmu; //never used by GameBoy 
CPU cpu; //CPU and GPU used in GameBoy 
GPU gpu; 

}; 

class CPU{ 
... 

private: 
MMU *mmu; 
}; 

class GPU{ 

... 

private: 
MMU *mmu; 

}; 

或:

class GameBoy{ 

public: 
GameBoy() 
: CPU(), gpu(&cpu.getMMU()) 
... 

private: 
CPU cpu; //CPU and GPU used in GameBoy 
GPU gpu; 

}; 

class CPU{ 
... 

private: 
MMU mmu; //arbitrarily chosen owner. GPU could have been the owner 
}; 

class GPU{ 

... 

private: 
MMU *mmu; 

}; 

我喜歡的第一個,因爲它好一點似乎更一致,但GameBoy從不使用MMU。

+0

爲什麼共享指針? –

+0

我應該把它放在我的描述中,但正如您從init列表中看到的那樣,MMU需要一個指向Cartridge的指針,並且CPU需要一個指向MMU的指針。有靜態分配的對象做這個更好的方法嗎? – DanB91

+0

Gameboy班是否全部使用三個? –

回答

8

我現在質疑這個設計,因爲這3班 (墨盒,CPU,MMU)將只被實例化一次。

沒有用戶會想要說,看他們的朋友玩遊戲嗎?流式傳輸命令並在主機上模擬它們比流式傳輸視頻具有更高的帶寬效率。沒有人願意和朋友一起做「鏈接模式」。永遠不會,先生。

也就是說,這是您的應用程序的某種基石,這實際上證明了Singleton的理由,這顯然是錯誤的。你目前的設計和功能不要求超過這個,但有絕對沒有任何理由鎖定自己。其次,即使他們只能實例化一次,有史以來,這可以有效地執行一些private訪問控制,絕對不需要全局狀態。

簡而言之,單身人士是現代編程中最糟糕的主意之一。永遠不要使用一個。

如果這一個是最好的,我應該留在shared_ptr?我已經讀了 它應該謹慎使用,但在這裏,似乎是有道理的,因爲 所有3個類互相依賴。

呃,沒有。爲什麼要使用指針呢?只需將它們直接作爲成員變量。交叉類依賴是沒有理由使用shared_ptr,只是使用T *。

+0

我的計劃是實際納入在線遊戲。現在,最初,我認爲不需要GameBoy的另一個實例,只是來回傳遞數據包而沒有任何抽象。現在我意識到我將使用GameBoy對象來表示第二個玩家。這是短視的。 根據我最近的編輯,如果2個對象(在這種情況下是GameBoy和MMU)共享一個對象(Cartridge),請使用原始指針?有沒有理由使用shared_ptr? – DanB91

+0

@ DanB91:'shared_ptr'僅用於共享*所有權*。僅僅需要引用一個對象並不能證明使用'shared_ptr'。在這種情況下,GameBoy對象可以毫無問題地擁有mmu/cart/cpu,所以沒有理由使用shared_ptr。 – Puppy

1

除了使Global對象/變量變得更加花哨之外,幾乎沒有理由使用Singleton。如果你發現一個好的設計來避免全局變量,那麼它很容易打賭它比單例更好。

一些(可爭議的)異常是記錄器類或對系統中本質上可能是全局資源的資源的訪問,例如共享內存。

至於使用shared_ptr與unique_ptr。堅持一個unique_ptr,除非你有一個很好的理由需要一個shared_ptr。這裏它們在功能上是等價的,但unique_ptr清楚地表明Gameboy類擁有三個對象,每個對象都有一個實例。還有一些其他答案中提到,你可以完全避免指針,但是使用它們也有好處。

我應該把它放在我的描述中,但正如您從init列表中看到的那樣,MMU需要一個指向Cartridge的指針,並且CPU需要一個指向MMU的指針。有靜態分配的對象做這個更好的方法嗎?

一種方法是拋棄初始列表,因爲你的構造函數有點複雜,並明確地處理順序。

GameBoy() 
    :cart(nullptr), 
    mmu(nullptr), 
    cpu(nullptr) 
{ 
    cart = new Cartrige(); 
    mmu = new MMU(cart); 
    cpu = new CPU(mmu); 
} 
+0

我沒有得到最後一部分。成員是按照聲明的順序初始化的,所以關於順序的確是一回事。 – chris

+0

是的,但這種方法是安全的,因爲如果將聲明(.h)和定義(.cpp)分開,很容易在未來的修改中擾亂順序。在這種情況下最好明確。 – slaterade

+0

這就是對imo的評論。評論這組聲明,並說不要改變順序和原因。 – chris

0

一個好的設計可以讓你同時運行多個仿真,即使這個要求在實踐中從未出現過。

我想你有兩個選擇,取決於依賴關係的工作方式。如果mmu需要墨盒,爲什麼不使墨盒成爲mmu的成員?而mmu是cpu的一員。或者,如果你想讓他們都可以在gameboy裏面進入,我認爲所有三人都會和gameboy一樣生活。將它們作爲unique_ptr或full-members(無指針)存儲在gameboy中,通過普通指針將它們傳遞給子類,然後在gameboy被銷燬時將它們刪除。

+0

刪除唯一指針。他們沒有理由。 –

0

變化是不變的,你應該有信心,當你想要改變你的代碼時,會有一段時間。這意味着如果你目前的設計不需要需要一個單身人士,那麼沒有理由限制自己。當前的實現允許更多的可擴展性。

至於shared_ptr,您可以使用,當你需要多個指針指向同共享,實例。例如,假設您有3個類別ABCBC都有一個指針BC之間共享A,一個實例的一個實例,因此只應被刪除後BC被刪除。在那個例子中你應該使用shared_ptr。否則你應該使用unique_ptr。因此你不應該使用shared_ptr。實際上,如果cart,mmucpu是具體類,而不是接口/基類,則不應使用任何類型的指針。

編輯:

爲何GameBoy類需要的CartridgeMMUCPU實例?爲什麼不只是一個CPU創建自己的MMU創建自己的Cartridge

+0

我可以做到這一點。但是,GameBoy需要一個加載ROM的方法。我認爲說cart-> loadROM()比mmu-> loadROM()更直觀。但是,也許消除指針比讓代碼更直觀一點更好。 假設MMU需要在CPU和GPU之間共享,並且CPU擁有完整的MMU對象。難道只有這樣我才能讓MMU成爲CPU(和GPU)中的指針嗎? – DanB91

+0

您可以使用getCart() - > loadROM(),因此更容易更改getCard()以根據購物車的位置返回getMMU() - > getCart()或購物車。 – Jarod42