2015-12-11 55 views
0

我很好奇,私有對象的屬性,如果這是assignement修改通過方法,它返回參考

class Foo { 
    int x_; 

    public: 
    int & x() { 
     return x_; 
    } 
}; 

我的老師正在assignement這樣的正確方法:obj.x() = 5; 但國際海事組織,這不是做這件事的正確方法,它並不明顯,在這裏使用setter會更好。這是違反清晰和乾淨的代碼?如果我們認爲我們應該像代碼不好的書一樣閱讀代碼,對嗎?誰能告訴我,如果我是對的? :)

+0

你能詳細闡述一下你在創建obj對象的地方嗎? 按照上面的類樣本,有一個基本問題是你將每個事物都保存爲私有的,所以實際上obj.x()不會在類之外工作。 如果你沒有指定訪問說明符,它默認爲私有的 – Ajay

+0

一般來說不是「錯誤」或「正確」,但是隻有數百萬種不同的做事方式,每種行爲都有點不同,如果你想要這種行爲(即揭露一個私人成員的引用),那就好了。看看例如'std :: vector',它的'[]'或'at()'返回一個引用,可以讓你修改這些值,沒有什麼不好的。 – user463035818

+0

順便說一句,在你的例子中變量和方法都是私人的,這使得它有點沒有意義.... – user463035818

回答

1

IMO,這代碼在進化方面不是一個好的做法。如果您需要提供一些更改檢查和格式設置,則必須重構可能成爲問題的類API。

  1. set_x()將是一種更清潔的方式。此外,它可以讓你檢查你的制定者的機制。
  2. 適當的吸氣劑get_x()x()也可以在返回之前應用一些邏輯(格式,任何...)。在你的情況下,你應該返回int而不是int&,因爲setter應該用於修改(不允許直接修改)。

實際上,這段代碼並沒有什麼意義......它返回一個對屬性的引用使其完全可修改。爲什麼不直接擁有公共財產呢?並避免創建一個額外的方法?

你想控制或不控制你的數據嗎?如果你這麼認爲,那麼你可能需要一個適當的吸氣和吸氣器。如果沒有,你可能不需要一種方法,只是公開。

總而言之,我會說你是對的,因爲你看到它的方式會讓它變得更好,容易出現不間斷的變化,更好的閱讀。

由於UNIX哲學提到:「清晰度規則:清晰度比聰明度要好。」

0

假設x()碰巧是public(或protected)成員該函數有效地暴露一個實現:是一個int舉行某處。無論是好還是壞都取決於上下文,而且就目前而言,上下文很少。

例如,如果x()實際上拼寫operator[](Key key)和與像std::vector<T>標運算符(在此情況下Key真的會std::size_t)或std::map<Key, Value>的容器類的一部分使用返回[非const]參考的是相當合理。另一方面,如果建議是針對一個類中基本上所有的成員都具有這樣的功能,那麼這個訪問本質上允許不受控制地訪問該類的狀態,這是一個相當不好的想法。對所有成員具有訪問功能通常是並且表明沒有抽象:成員的設置者/獲取者往往表示該類實際上只是值的集合,並且所有public成員的struct可能服務於目的也是如此,如果不是更好的話。實際抽象中,訪問數據的事務傾向於暴露與其實際表示無關的接口。

0

在此示例中,返回(非const)引用的效果與將變量設置爲public的效果相同。任何封裝都被破壞了。但是,這並不是一件壞事。這種情況可以幫助很多,當變量是複雜結構的一部分時,並且您想爲該變量提供一個簡單的接口。例如

class Foo { 
    std::vector<std::list<std::pair<int,int>>> values; 
    public: 
     int& getFirstAt(int i){ 
      return values[i].[0].first; 
     } 
}; 

現在,你必須在i位置易於訪問的第一個元素的第一個元素,不需要每次都寫的充分體現。

或者你的類可以使用內部的一些容器,但它是什麼容器應該是一個私人的細節,然後代替露出滿容器,你可以公開引用的元素:

class Bar { 
    std::vector<int> values; // vector is private!! 
    public: 
     int& at(int i){   // accessing elements is public 
      return values.at(i); 
     } 
}; 
0

一般來說,這樣的代碼會使讀者感到困惑。

obj.x() = 5; 

然而,它並不罕見,以滿足例如下列代碼

std::vector<int> v = { 1, 0 }; 
v.back() = 2; 

這是C++語言的缺點。

在C#中,通過引入屬性避免了此缺點。

至於這個特殊的例子,最好是使用getter和setter。

例如

class Foo { 
    int x_; 

    public: 
    int get_value() const { return x_; } 
    void set_value(int value) { x_ = value; } 
}; 

在這種情況下該接口可以保持,而實現可以改變。