我很好奇这是否是正确的分配方式
class Foo {
int x_;
public:
int & x() {
return x_;
}
};
我的老师正在这样做:obj.x() = 5;
但IMO认为这不是正确的做法,不明显,在这里使用setter会更好。是否违反了清晰明了的代码?如果我们采取规则,我们应该读代码就像一本代码不好的书,我是对的吗?任何人都可以告诉我,如果我是对的吗? :)
答案 0 :(得分:1)
IMO,这个代码在进化方面不是一个好习惯。如果您需要提供一些更改检查,格式化,您必须重构您的类API,这可能会成为时间问题。
def analyser (empfaenger):
strlaenge= len(empfaenger)
record = 'RECORD NAME IS'
stufennummer2 = empfaenger.split()
if len(stufennummer2) < 2:
print('Line too short')
return
更清洁。此外,它将允许您在您的二传手中检查机制。 set_x()
或get_x()
也可以在返回之前应用一些逻辑(格式,任何......)。在您的情况下,您应该返回x()
而不是int
,因为应该使用setter进行修改(不允许直接修改)。实际上,这段代码确实没有意义......它返回一个属性的引用,使其完全可修改。为什么不直接拥有公共财产呢?并避免创建其他方法?
您是否想要控制数据?如果你这么认为,那么你可能想要一个合适的吸气剂和二传手。如果没有,您可能不需要方法,只需公开。
总而言之,我会说你是对的,因为你看到它的方式会使它在一段时间内变得更好,容易发生不间断的变化,更好地阅读。
正如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; }
};
在这种情况下,可以保留界面,同时可以改变实现。