2012-01-27 78 views
4

我有一個CUDA工程一堆類,大多是榮耀struct s,不構成依賴於對方:封裝vs結構 - 這被認爲是不好的風格?

class A { 
    public: 
     typedef boost::shared_ptr<A> Ptr; 
     A(uint n_elements) { ... // allocate element_indices }; 
     DeviceVector<int>::iterator get_element_indices(); 
    private: 
     DeviceVector<int> element_indices; 
} 

class B { 
    public: 
     B(uint n_elements) { 
      ... // initialize members 
     }; 
     A::Ptr get_a(); 
     DevicePointer<int>::iterator get_other_stuff(); 
    private: 
     A::Ptr a; 
     DeviceVector<int> other_stuff; 
} 

DeviceVector是隻是一個包裝圍繞thrust::device_vector S和::iterator可以轉換爲一個原始設備指針。這是必需的,因爲自定義內核被調用並需要處理設備內存。

現在,我不關心封裝,但

  • 裸指針的數據已經被暴露,所以使用AB類可在GPU上
  • 運行自定義內核默認構造函數是不希望的話,設備存儲器應當自動分配 - 上A>shared_ptr<T>
  • 只有極少數方法和B需要

所以,我們可以簡單地使用結構

struct A { 
    void initialize(uint n_elements); 
    DeviceVector<int> element_indices; 
} 

struct B { 
    void initialize(uint n_elements); 
    A a; 
    DeviceVector<int> other_stuff; 
} 

我不知道我是否正確,在封裝的意義上,這實際上相當於讓生活更簡單。如果是這樣,那麼整個概念有什麼不妥之處,並且可能會在某個時候咬人?

+4

C++中類和結構之間的唯一區別是默認可見性(私有類,公共結構)。如果你沒有指定任何參數,編譯器仍然會給你一個默認的構造函數,所以我不確定你的結構例子中初始化函數的用途是什麼。 – jpm 2012-01-27 20:46:13

+2

你的問題確實在問「封裝vs公共數據」。 jpm關於使用'struct'是正確的。 – 2012-01-27 20:56:25

+0

「class」和「struct」在對象設計中有一些更強的內涵,它的價值在於什麼。 C++是混淆這些術語的罪魁禍首。 :) – 2012-01-27 22:23:17

回答

1

這是一個折衷。

使用值結構可以將一組數據組合在一起,非常簡單。如果你開始加入很多輔助程序並且依賴它們超出它們的預期用途,它們可能非常笨拙。對自己的時間和使用方式嚴格要求,他們都很好。對這些對象使用零方法是讓自己明白這一點的好方法。

你可能有一些你用來解決問題的類,我將它稱爲一個模塊。在模塊中具有價值結構很容易推理。在模塊之外,你必須希望有良好的行爲。你沒有嚴格的接口,所以你必須希望編譯器會警告你濫用。

鑑於這種說法,我認爲它們更適合匿名或詳細的命名空間。如果他們最終進入公共界面,人們往往會添加糖。用接口刪除糖或將其重構爲第一類對象。

我認爲它們更適合作爲const對象。你陷入的問題是你(試圖)維持它在整個生命週期中使用的任何地方的這個「對象」的不變性。如果不同的抽象層次想讓它們有輕微的突變,請複製一份。命名參數習語對此很有幫助。

Domain Driven Design給出了有關該主題的深思熟慮的治療。它表徵瞭如何理解和促進設計的更實際意義。

Clean Code也從不同的角度討論了這個話題。這是更多的morality書。

這兩個都是很棒的書籍,一般在本主題之外推薦。

+0

謝謝你的回答,我對於沒有方法的'struct'如何看待自己至少與'class'不同的觀點基本相同。把這些'struct'放入一個命名空間(或者將可見性限制在將要使用它們的唯一類中?)是一個好主意。 – bbtrb 2012-01-28 22:51:27

2

讓它變得簡單。在你需要之前不要引入抽象和封裝。

2

保持數據成員私密是一種好習慣。起初可能你的結構很小,沒有或有幾個成員函數,並且需要公開數據成員。然而,隨着您的計劃的發展,這些「結構」往往會增長並擴散。在你知道它之前,你所有的代碼都依賴於其中一個結構的內部結構,並且稍微改變它就會在整個代碼庫中發生混響。

即使您需要將裸指針指向數據,仍然可以通過getter來實現。您可能想要更改數據在內部的處理方式,例如, G。用std :: vector替換原始數組。如果你的數據成員是私人的,並且你正在使用getter,那麼你可以做到這一點,而不會影響使用你的類的任何代碼。此外,getter讓你強制執行const,然後通過返回一個const指針來使一段特定的數據成爲只讀。

這是一個多一點的工作,但大部分時間它從長遠來看都有回報。