通过返回引用的方法修改私有对象属性

时间:2015-12-11 09:35:13

标签: c++

我很好奇这是否是正确的分配方式

class Foo { 
    int x_;

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

我的老师正在这样做:obj.x() = 5; 但IMO认为这不是正确的做法,不明显,在这里使用setter会更好。是否违反了清晰明了的代码?如果我们采取规则,我们应该读代码就像一本代码不好的书,我是对的吗?任何人都可以告诉我,如果我是对的吗? :)

4 个答案:

答案 0 :(得分:1)

IMO,这个代码在进化方面不是一个好习惯。如果您需要提供一些更改检查,格式化,您必须重构您的类API,这可能会成为时间问题。

  1. def analyser (empfaenger): strlaenge= len(empfaenger) record = 'RECORD NAME IS' stufennummer2 = empfaenger.split() if len(stufennummer2) < 2: print('Line too short') return 更清洁。此外,它将允许您在您的二传手中检查机制。
  2. 正确的getter set_x()get_x()也可以在返回之前应用一些逻辑(格式,任何......)。在您的情况下,您应该返回x()而不是int,因为应该使用setter进行修改(不允许直接修改)。
  3. 实际上,这段代码确实没有意义......它返回一个属性的引用,使其完全可修改。为什么不直接拥有公共财产呢?并避免创建其他方法?

    您是否想要控制数据?如果你这么认为,那么你可能想要一个合适的吸气剂和二传手。如果没有,您可能不需要方法,只需公开。

    总而言之,我会说你是对的,因为你看到它的方式会使它在一段时间内变得更好,容易发生不间断的变化,更好地阅读。

    正如UNIX哲学所提到的:“清晰规则:清晰度胜于聪明。”

答案 1 :(得分:0)

假设x()碰巧是public(或protected)成员,该函数有效地公开了一个实现:这是一个int某个地方。无论好坏取决于背景,因为它的背景很少。

例如,如果x()实际拼写为operator[](Key key),而且容器类的一部分具有下标运算符,例如std::vector<T>(在这种情况下Key真的是{{1} }}或std::size_t使用返回[非 - std::map<Key, Value>]引用是非常合理的。

另一方面,如果建议是为类中的所有成员提供此类函数,那么这是一个相当糟糕的主意,因为此访问实质上允许对类的状态进行不受控制的访问。拥有所有成员的访问功能通常并且表明也没有抽象:拥有成员的setter / getter往往表明该类实际上只是一个值的集合,而const包含所有struct如果不是更好的话,成员也可能会达到目的。访问数据的实际抽象倾向于暴露一个独立于其实际表示的接口。

答案 2 :(得分:0)

在此示例中,返回(非常量)引用的效果与将变量设置为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);
       }
};

答案 3 :(得分: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; }
};

在这种情况下,可以保留界面,同时可以改变实现。