2013-03-28 23 views
4

我知道在您的班級中設置公共字段被認爲是一個壞主意。但是當你的課程包含許多分層數據結構和領域時,最好的方法是什麼?例如:安裝程序/獲取程序和分層數據結構

class A {B d1; C d2; D d3;} 
class B {E d4; F d5;} 
class E {G d6; int d7;} 

在C中,訪問這樣的數據結構是很容易的,例如, ptr_to_A-> d1.d4.d7等等......但是當我們使用setter/getters時,該怎麼辦?當在C++中使用setter和getter時,像A.get_d1()。get_d4()。get_d7()這樣的表達式似乎並不方便,並且它們強制返回引用。由於一些結構相當大,所以按價值回報似乎是一個可怕的想法。

您在這些情況下使用哪種方法或編碼風格?也許擺脫setter/getters和公開這些領域?

回答

2

我知道在班上有公共領域被認爲是一個壞主意。

這是一個來自過去十年Java開發的聲明。你應該考慮一個成員應該是公開還是私人的成員一個成員。有時候公共數據成員是正確的想法。考慮以下問題:

  1. 我是否需要對此成員保持不變?
  2. 這個成員可以有一個無效值嗎?
  3. 我是否希望界面給出此成員的替代表示形式?

如果上述任何問題的答案是肯定的,那麼您可能需要使用getter。

還要考慮是否真的有意義,單獨設置成員。也許你應該用構造函數設置成員,並且你想提供一些其他的接口來修改這些成員。

當在C++中使用getter和setter方法,這樣的表達式A.get_d1()。get_d4()。get_d7()看起來很方便

不雖然這不是太不凡有相當深的嵌套的數據結構,通常一段特定的代碼不應該深入研究它。如果確實如此,我想它可能做得比應該做得更多,超越了它的單一責任。但是,如果它是一個共同的任務,從A對象獲取d7,也許A應該將其暴露在它的接口:

int A::get_d7 { 
    return get_d1().get_d4().get_d7(); 
} 

由於一些結構是相當大的,由價值迴歸似乎是一個可怕的想法。

實際上,用現代C++,這根本不是問題。按值傳遞應該被認爲是對象傳遞的默認模式。這是因爲臨時對象現在可以從中移出,這實質上是一種非常有效的複製形式。

+0

但是,當按值返回時,它肯定會創建一個數據結構的副本。如果其中一個嵌套數據結構很大,考慮到我只想讀取一個字段,這不是一個好主意。 – jbgs

+0

@jbgs這取決於它返回的內容。如果它返回一個成員對象,是的,它將不得不復制它。 –

+0

是的,這些嵌套的數據結構是成員對象。實際上我認爲常見的C++編碼風格並不適合我正在開發的這種應用(微電子仿真)。 – jbgs

1

如果你只是使用類作爲一個純粹的數據結構,並有與要封裝的數據沒有行爲,然後用struct,而不是直接訪問的字段。 Bjarne Stroustrup recommends this approach。這相當於使用class並聲明所有成員爲public,但將其稱爲struct反而更清楚地表明它只不過是簡單的數據收集。

如果您不僅僅是存儲數據,而是使用getters和setter。

當在C++中使用getter和setter方法,這樣的表達式 A.get_d1()。get_d4()。get_d7()似乎並不方便,而且他們強迫 返回引用。由於一些結構相當大,按價值返回 似乎是一個可怕的想法。

不,您可以選擇是通過引用還是按值返回。

+0

大多數類也包括一些成員函數。 – jbgs

2

在我的編碼風格中,類不應公開「原始」數據成員,而只能是getter和setter(即使它們是簡單的單行方法)。

這是因爲未來可以升級代碼,單線方法可以擴展到更復雜的東西(或者可以添加一些僅用於調試的構建功能來檢查某些不變量等),所以最好讓客戶端的接口保持一致(如果你暴露「原始」數據成員,這是不可能的)。

您可以避免使用前綴get_(),只需將該數據成員視爲一個簡單的(不含get_...)名稱的「屬性」即可。

class Shape 
{ 
public: 
    .... 

    COLORREF Color() const // Just Color() i.e. the property name, without get_... 
    { 
    return m_color; 
    } 

private: 
    COLORREF m_color; 
}; 

並編寫客戶端代碼,如:

Shape s; 
COLORREF someColor = s.Color(); 

這看起來好像沒什麼問題。

對於您可以像使用語法二傳手:

Shape& Color(COLORREF color) 
{ 
    m_color = color; 
    return *this; 
} 

,並寫出這樣的客戶端代碼:

Shape s; 
s.Color(...).Draw(); // set color and draw shape 

如果屬性的類型是東西比COLORREF更復雜(這是一個32位的DWORD),你可以使用一個模式,如:

std::wstring Name() const // getter 
{ 
    return m_name; 
} 

Shape& Name(std::wstring name) // setter 
{ 
    // Pass by value and move from the value (C++11 move semantics) 
    m_name = std::move(name); 

    return *this; 
}